React Native Expo:android 上出现网络错误

问题描述 投票:0回答:6

我在我的应用程序中使用 axios。当我打开应用程序后第一次发出发布请求时,它失败并出现以下错误。从第二次开始,就没有任何问题了。

Network Error
- node_modules/axios/lib/core/createError.js:15:17 in createError
- node_modules/axios/lib/adapters/xhr.js:81:22 in handleError
- node_modules/event-target-shim/dist/event-target-shim.js:818:20 in EventTarget.prototype.dispatchEvent
- node_modules/react-native/Libraries/Network/XMLHttpRequest.js:600:10 in setReadyState
- node_modules/react-native/Libraries/Network/XMLHttpRequest.js:395:6 in __didCompleteResponse
- node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10 in emit
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:416:4 in __callFunction
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:109:6 in __guard$argument_0
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:364:10 in __guard
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
* [native code]:null in callFunctionReturnFlushedQueue

我正在真实的 Android 设备上运行,通过 http://my_ip:my_port/ 连接到真实的服务器。我尝试在 kotlin 中创建一个本机 android 项目,并且它运行正常,没有任何问题

这是我的代码:

const upload = () => {
    setAnalyzing(true);

    axios.post(URL_PREDICT, formBody(), {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    }).then(handleSuccess)
      .catch(handleFail);
  }

  const formBody = () => {
    const photo = {
      uri: image,
      type: 'image/jpeg',
      name: 'photo.jpg',
    };
    const form = new FormData();
    form.append("file", photo);
    return form;
  };

  const handleFail = (error) => {
    console.log(error)
    console.log(error?.response?.data);
    setAnalyzing(false);
    toggle();
    alert("ERROR " + error);
  };

  const handleSuccess = response => {
    console.log('success...');
    setAnalyzing(false);
    toggle();
    console.log(response);
    navigation.navigate('Result', response);
  };

知道是什么原因造成的吗?

android react-native axios fetch general-network-error
6个回答
10
投票

解决方案1

确保 “http://” 在您的 URL 地址中。

  1. localhost 更改为您的 ip
  2. 添加http://

http://192.168.43.49:3000/user/

解决方案2

我遇到了同样的问题,它发生在 Android 中,但在 IOS 中运行良好。 我猜这个问题是关于 Flipper Network 的。

有一段时间,我评论了

initializeFlipper(this, getReactNativeHost().getReactInstanceManager())

在此文件中

/android/app/src/main/java/com/{your_project}/MainApplication.java

解决方案3

无论谁仍在为这个问题苦苦挣扎。这是因为 Flipper 网络插件而发生的。 我禁用了它,一切正常。

我的解决方法是注释掉第 43 行

38      NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39      NetworkingModule.setCustomClientBuilder(
40          new NetworkingModule.CustomClientBuilder() {
41            @Override
42            public void apply(OkHttpClient.Builder builder) {
43      //        builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44            }
45          });
46      client.addPlugin(networkFlipperPlugin);

在此文件中

android/app/src/debug/java/com/**/ReactNativeFlipper.java

解决方案4

不需要添加

Access-Control-Expose-Headers

需要这个:

                headers:{
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Accept': 'application/json'}
            }

我调整了你的服务器,它起作用了。


8
投票

我认为您正在使用

expo-image-picker

这里有两个独立的问题正在发生。假设我们从

imageUri
获得
image-picker
,那么我们将使用以下代码行从前端上传。

const formData = new FormData();
formData.append('image', {
 uri : imageUri,
 type: "image",
 name: imageUri.split("/").pop()
});

第一个问题是

imageUri
本身。如果假设照片路径是
/user/.../path/to/file.jpg
。然后,Android 中的文件选择器会将
imageUri
值指定为
file:/user/.../path/to/file.jpg
,而 iOS 中的文件选择器会将
imageUri
值指定为
file:///user/.../path/to/file.jpg

第一个问题的解决方案是在android中的formData中使用

file://
代替
file:

第二个问题是我们没有使用正确的

mime-type
。它在 iOS 上运行良好,但在 Android 上则不行。更糟糕的是,文件选择器包将文件类型指定为“图像”,并且没有指定正确的 mime 类型。

解决方案是在字段类型的formData中使用适当的

mime-type
。例如:
.jpg
文件的 mime 类型为
image/jpeg
.png
文件的 mime 类型为
image/png
。我们不必手动执行此操作。相反,您可以使用一个非常著名的 npm 包,称为 mime

最终的工作解决方案是:

import mime from "mime";

const newImageUri =  "file:///" + imageUri.split("file:/").join("");

const formData = new FormData();
formData.append('image', {
 uri : newImageUri,
 type: mime.getType(newImageUri),
 name: newImageUri.split("/").pop()
});

2
投票

如果有人不喜欢赞成的答案或仍然面临问题,那么我的答案可能会有所帮助。确保您的模拟器/设备时间与现实世界时间相同,以避免证书验证错误,否则手动设置正确的时间并重新加载应用程序。


0
投票

在尝试使用模拟器中的 expo 从 React Native 应用程序向我的 rust actix Web 服务器发送 API 请求时,我遇到了同样的问题。 在花了几个小时研究这个问题但无法找到解决方法后,我在 ngrok 中找到了解决方案。它创建了一条从本地服务器到开放网络的隧道,因此基本上您可以从 RN 应用程序调用您的 api 端点,就好像它不会在您的本地主机中运行一样。

错误立即得到修复。希望它能有所帮助,即使我知道这不是解决办法,而是解决您问题的方法。


0
投票

万一有人再次遇到麻烦..我发现对于android,ip需要是10.0.2.2,但对于ios,它需要是127.0.0.1。

下面的代码允许您独立设置它们:

import { Platform } from 'react-native';

const LOCALHOST = Platform.OS === 'ios' ? 'http://127.0.0.1:8000' : 'http://10.0.2.2:8000';
export const API_BASE_URL = LOCALHOST + '/api/v1/';

0
投票

截至 2023 年 11 月,我仍然遇到此问题,并且此处的解决方案均不起作用。

使用 FileSystem 的 uploadAsync 效果很好,唯一的缺点是它不允许上传多个文件,这对我来说是一个大问题。

npx expo install expo-file-system

如果您只上传单个文件,那么您可以使用此片段


import {uploadAsync} from "expo-file-system"
import axios from "axios"

let url = "" // your endpoint
let image = {} //imagePickerResult;
let sendData = {} // Plain object
let formData = new FormData(); // sendData  keys and values appended to formdata plus the image
 
if (Platform.OS == "android") {
    let res = await uploadAsync(url, image.uri, {
        fieldName: "nameOfField", 
        httpMethod: "PATCH", 
        mimeType: "image/*", 
        uploadType: FileSystemUploadType.MULTIPART, 
        headers: {
            // access token bearears auth and what-not
        }, 
        parameters: sendData // This would be the BODY of the request
    })
    return res
} else {
    let res = await axios.patch(url, formData);

    return res
}

© www.soinside.com 2019 - 2024. All rights reserved.