当我使用react-native init (RN版本0.29.1)创建一个全新的项目,并在渲染方法中获取公共facebook演示电影API时,它抛出了一个网络请求失败。有一个非常无用的堆栈跟踪,我不能调试网络请求在chrome控制台。这是我发送的fetch:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });

当前回答

对我来说……我已经有https了…当我在头文件中添加“Content-type”:“application/json”时,这个问题就消失了

headers: {
  Authorization: token,
  'Content-type': 'application/json',
  /** rest of headers... */
}

平台:安卓

其他回答

只需添加

<uses-permission android:name="android.permission.INTERNET" />

    <application
      android:usesCleartextTraffic="true"

然后将获取URL域(localhost)替换为您的IP地址,

const dataRaw = await fetch('http://192.168.8.102:4000');

修复TypeError:在Android调试版本中将文件上传到http而不是https时网络请求失败

在react-native 0.63.2(我正在测试)或更高版本中,如果只是使用fetch将文件上传到http(而不是https)服务器,将会遇到TypeError:网络请求失败。

在这里,我使用axios@0.27.2作为运行在Android手机上的客户端,成功地将文件上传到react-native-file-server作为运行在另一台Android手机上的服务器。

客户端需要编辑JAVA和JS代码,服务器不需要编辑JAVA代码。

在调试构建中,必须注释掉这个文件android/app/src/debug/java/com/YOUR_PACKAGE_NAME/ReactNativeFlipper.java中的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:usesCleartextTraffic="true"下的<应用程序的android/app/src/main/AndroidManifest.xml,在我的测试,这是不必要的调试和发布构建。

  onFileSelected = async (file) => {
    // API ref to the server side BE code `addWebServerFilter("/api/uploadtodir", new WebServerFilter()`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L356
    // could not be 'localhost' but IP address
    const serverUploadApi = 'http://192.168.1.123:8080/api/uploadtodir';

    // the folder on server where file will be uploaded to, could be e.g. '/storage/emulated/0/Download'
    const serverFolder = '/storage/emulated/0/FileServerUpload';

    const fileToUpload = {
      // if want to upload and rename, it can be `name: 'foo.bar'`, but can not be 'foo'
      // only if your server upload code support file name without type, on our server
      // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L372
      // will cause java.lang.StringIndexOutOfBoundsException in substring()
      name: file.name,

      // type is necessary in Android, it can be 'image/jpeg' or 'foo/bar', but can not be
      // 'foo', 'foo/', '/foo' or undefined, otherwise will cause `[AxiosError: Network Error]`
      type: 'a/b',

      uri: Platform.OS === 'android' ? file.uri : file.uri.replace('file://', ''),
    };

    const form = new FormData();
    form.append('path', serverFolder);
    form.append('uploadfile', fileToUpload);

    // ref to the server side FE code `this.axios.post("/api/uploadtodir", parms, config)`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/fileserverwebdoc/src/views/Manage.vue#L411
    let res = await axios.post(serverUploadApi, form, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: function (progressEvent) {
        console.warn(progressEvent);
      },
    });

    // ref to the server side BE code `return newFixedLengthResponse("Suss");`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L380
    if (res.data === 'Suss') {
      console.warn('Upload Successful');
    } else if (res.data === 'fail') {
      console.warn('Upload Failed');
    }
  };

Android用户:

Replace localhosts to a Lan IP addresses because when you run the project on an Android device, localhost is pointing to the Android device, instead of your computer, example: change http://localost to http://192.168.1.123 If your request URL is HTTPS and your Android device is under a proxy, assume you have installed User-added CA(like burp suite's CA or Charles's CA) in your Android device, make sure your Android version is below Nougat(7.0), because: Changes to Trusted Certificate Authorities in Android Nougat User-added CAs Protection of all application data is a key goal of the Android application sandbox. Android Nougat changes how applications interact with user- and admin-supplied CAs. By default, apps that target API level 24 will—by design—not honor such CAs unless the app explicitly opts in. This safe-by-default setting reduces application attack surface and encourages consistent handling of network and file-based application data.

对于fetch API,你应该在.then中处理错误情况。

例如:

fetch(authURl,{ method: 'GET'})
.then((response) => {      
  const statusCode = response.status;
  console.warn('status Code',statusCode);
  if(statusCode==200){
    //success code
  }else{
    //handle other error code
  }      
},(err) => {
  console.warn('error',err)
})
.catch((error) => {
  console.error(error);
  return error;
});

这不是答案,而是选择。 我切换到https://github.com/joltup/rn-fetch-blob 它既适用于表单数据,也适用于文件