React Native 0.6图片上传服务器遇网络请求失败等问题求助
解决React Native 0.6图片上传"Network Request failed"及返回数据异常问题
我看你在React Native 0.6 + Genymotion环境下遇到了图片上传的一系列棘手问题:fetch报"Network Request failed",RNFetchBlob响应慢到离谱,Axios返回200状态但拿不到有效数据。结合你给出的代码,我整理了几个核心问题和对应的修复方案:
一、先搞定Genymotion的网络连通性
Genymotion模拟器的网络配置是这类问题的高发区,先排查这个基础问题:
- 先在模拟器自带的浏览器里访问你的服务器地址
http://web001.XXX.com:8000,如果打不开,说明模拟器和服务器之间的网络通路有问题:- 把Genymotion的网络模式切换为桥接模式(在VirtualBox的虚拟机设置里修改),让模拟器和你的电脑处于同一网段
- 如果服务器是本地搭建的,别用
localhost或127.0.0.1,换成你电脑的局域网IP(比如192.168.x.x)——因为模拟器的localhost指向它自己,不是你的电脑
- 同时确认服务器没有设置IP白名单,拒绝了模拟器的请求
二、修正FormData的构造错误
你的代码里UplodedFile.append('file',{ type:'image/jpeg', uri : this.state.avatarSource , name:'file.jpeg'})有明显的错误:
this.state.avatarSource是一个{uri: response.uri}的对象,你应该直接传response.uri或者this.state.avatarSource.uri,而不是整个对象- Android和iOS的uri格式不一样,iOS是
file://开头,Android可能是content://或直接文件路径,需要统一处理
修正后的Send方法:
import { Platform } from 'react-native'; Send = async () => { let url = "http://web001.XXX.com:8000/api/prediction/check_prediction/"; let UplodedFile = new FormData(); // 处理不同平台的uri格式 const fileUri = Platform.OS === 'android' ? this.state.avatarSource.uri : this.state.avatarSource.uri.replace('file://', ''); UplodedFile.append('file', { type: 'image/jpeg', uri: fileUri, name: 'file.jpeg' }); // 不要手动设置Content-Type,让fetch自动生成带boundary的multipart/form-data头 fetch(url, { method: 'POST', body: UplodedFile, headers: { // 如果服务器需要认证,在这里加Authorization头,比如: // 'Authorization': 'Bearer your-token-here' } }) .then(response => { // 先检查响应状态再转JSON if (!response.ok) { throw new Error(`请求失败!状态码:${response.status}`); } return response.json(); }) .then(response => { console.log("上传成功!"); console.log("返回数据:", response); }) .catch(error => { console.error("上传出错:", error); }); }
三、检查权限配置
别漏掉必要的系统权限,否则也会导致上传失败:
- Android端:在
android/app/src/main/AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- iOS端:在
ios/项目名/Info.plist里添加相册访问权限说明:
<key>NSPhotoLibraryUsageDescription</key> <string>需要访问相册以选择上传的图片</string>
四、解决Axios返回200但空数据的问题
用Axios时同样要注意FormData的构造,另外可以开启调试模式查看请求细节:
import axios from 'axios'; import { Platform } from 'react-native'; Send = async () => { const url = "http://web001.XXX.com:8000/api/prediction/check_prediction/"; const formData = new FormData(); const fileUri = Platform.OS === 'android' ? this.state.avatarSource.uri : this.state.avatarSource.uri.replace('file://', ''); formData.append('file', { uri: fileUri, name: 'file.jpeg', type: 'image/jpeg' }); try { const response = await axios.post(url, formData, { // 让Axios自动处理multipart/form-data的boundary,不要手动设置Content-Type headers: { // 这里加其他必要的头信息,比如认证 }, // 开启调试,接收所有状态码的响应 validateStatus: (status) => true }); console.log("响应状态码:", response.status); console.log("响应数据:", response.data); } catch (error) { console.error("Axios请求错误:", error); } }
五、优化RNFetchBlob的响应速度
RNFetchBlob慢大概率也是网络问题,你可以设置超时时间并确认网络配置:
import RNFetchBlob from 'rn-fetch-blob'; Send = async () => { const url = "http://web001.XXX.com:8000/api/prediction/check_prediction/"; const formData = new FormData(); const fileUri = this.state.avatarSource.uri; formData.append('file', { uri: fileUri, name: 'file.jpeg', type: 'image/jpeg' }); RNFetchBlob.fetch('POST', url, { // 让RNFetchBlob自动处理multipart/form-data }, formData) .setTimeout(30000) // 设置30秒超时,避免无限等待 .then(res => { console.log("RNFetchBlob响应:", res.json()); }) .catch(err => { console.error("RNFetchBlob错误:", err); }); }
建议先从网络连通性和FormData构造这两个最常见的问题入手,应该能解决你的"Network Request failed"和返回空数据的问题。
内容的提问来源于stack exchange,提问作者Omar Trigui




