React Native Expo:android 上的网络错误

问题描述

我在我的应用中使用 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

我正在通过 http://my_ip:my_port/ 连接到真实服务器的真实 android 设备上运行。我通过在 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);
  };

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

解决方法

我认为您正在使用 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 上运行不正常。更糟糕的是,file-picker 包将文件类型指定为“图像”,而没有提供正确的 MIME 类型。

解决方案是在字段类型的formData中使用适当的mime-type。例如:.jpg 文件的 MIME 类型为 image/jpeg.png 文件为 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()
});
,

解决方案 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'}
            }

我调整了你的服务器,它可以工作了。

,

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...