当我使用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);
      });

当前回答

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.

其他回答

在我的例子中,Android模拟器没有连接到Wi-Fi。

看到这里安卓工作室-安卓模拟器Wifi连接没有互联网

为了找到根源问题,我使用XMLHttpRequest而不是获取,并在发送请求后抛出一个异常的消息,告诉实际问题HTTP_1_1_REQUIRED。

显然,react本机(在我的情况下v0.59)只支持http/1.1,然后我在web服务器上禁用了http/2。

如果你的网络服务器是IIS,看看这个问题的答案

希望这能有所帮助。

修复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');
    }
  };

如果你在REST api中使用docker,我的一个工作案例是将主机名:http://demo.test/api替换为机器ip地址:http://x.x.x.x/api。你可以通过检查你的无线网络的ipv4来获取IP。你的手机也应该有wifi。

这对我有用,android使用一个特殊类型的IP地址10.0.2.2然后端口号

import { Platform } from 'react-native';

export const baseUrl = Platform.OS === 'android' ?
    'http://10.0.2.2:3000/'
: 
'http://localhost:3000/';