React Native中Axios发FormData请求安卓端报Network Error
问题表现
基于axios + React Native实现FormData提交、图片上传到Node.js服务端的功能,相同代码在iOS端可正常完成数据提交、图片上传全流程,在安卓端运行时直接抛出如下错误:
[AxiosError: Network Error]
对应的原有调用代码如下:
const handleSubmit = async (listing, { resetForm }) => { const data = new FormData(); listing.images.forEach((image, index) => data.append("images", { name: `product${Math.floor(Math.random() * 1000)}.`, uri: image, }) ); const res = await axios .post("http://192.168.43.8:5000/products/addProduct", data, { headers: { "Content-Type": "multipart/form-data", }, //tried adding this but didn't work out transformRequest: (data) => data, }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); // handle error }); } }
React Native调试器捕获的错误截图如下:
故障原因
这个是React Native安卓端特有的兼容问题,核心原因有3个,iOS端因为系统网络层自动做了兼容处理所以不会触发:
- 安卓9及以上版本默认禁止所有明文HTTP请求,当前调用的服务端地址是
http://开头的非加密地址,会被安卓系统网络层直接拦截 - 传入FormData的文件对象缺少必填的
type(MIME类型)字段,安卓端无法自动识别本地文件类型,序列化请求体时直接失败 - 手动设置
Content-Type: multipart/form-data请求头会丢失multipart格式必需的boundary分隔符,iOS会自动补全这个分隔符,安卓不会,会导致服务端无法解析请求,请求直接在网络层被拦截 - 原有代码里的文件名后缀不完整,末尾只有
.没有实际后缀,也会提升安卓端的文件识别失败概率
修复方案
按以下步骤逐一修改即可解决:
- 放开安卓端明文HTTP请求限制
打开安卓项目路径下的android/app/src/main/AndroidManifest.xml文件,找到<application>标签,添加android:usesCleartextTraffic="true"属性,允许调试阶段访问本地HTTP服务,生产环境建议将服务端替换为HTTPS地址。 - 补全FormData内的文件参数
追加图片到FormData时,补全文件后缀和必填的type字段,示例修改:listing.images.forEach((image, index) => data.append("images", { name: `product${Math.floor(Math.random() * 1000)}.jpg`, // 补全文件后缀,根据实际图片格式调整为jpg/png等 uri: image, type: 'image/jpeg' // *安卓端必填*,和实际图片格式对应,png格式填image/png }) ); - 删除错误的请求配置
移除手动设置的Content-Type: multipart/form-data请求头,以及无效的transformRequest配置:axios识别到传入参数为FormData对象时,会自动生成带正确boundary的Content-Type头,手动设置反而会导致格式错误。修改后的请求部分代码参考:const res = await axios .post("http://192.168.43.8:5000/products/addProduct", data) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); - 额外注意:React Native 0.60及以上版本不要额外引入第三方FormData polyfill,直接使用RN全局自带的FormData对象即可,第三方实现普遍存在安卓端兼容问题。
内容的提问来源于stack exchange,提问作者Sb Zakaria
相关产品推荐
相关产品推荐

