React Native iOS端上传图片报“Network request failed”问题求助
我之前在Expo项目里碰到过几乎一模一样的iOS真机上传问题,结合你提供的信息(其他请求正常、Postman测试有效、试过常见方案无效),给你几个精准的排查点和解决办法:
1. 不要手动设置Content-Type: multipart/form-data头
这是很多人踩的坑:当你用fetch发送FormData时,React Native会自动生成带正确boundary的Content-Type头,手动添加反而会导致boundary不匹配,引发请求失败。你之前尝试添加这个头的操作可能是反效果,建议完全移除这个自定义头,让fetch自动处理。
2. 用Expo FileSystem重新处理图片URI(解决iOS私有路径问题)
iOS真机上Expo ImagePicker返回的file://开头的URI有时候会有路径权限问题,试试用expo-file-system把图片复制到更稳定的目录,再用新URI上传:
import * as FileSystem from 'expo-file-system'; // 复制图片到Expo的缓存目录 const newUri = FileSystem.cacheDirectory + filename; await FileSystem.copyAsync({ from: localUri, to: newUri }); // 构造FormData时用新的URI const formData = new FormData(); formData.append("file", { uri: newUri, name: filename, type: mime.lookup(newUri) || "image/jpeg" });
3. 读取图片为Blob再上传(绕开URI路径限制)
你试过base64转Blob,但可能转换方式不对,试试用Expo FileSystem直接读取base64再转Blob的方式:
import * as FileSystem from 'expo-file-system'; // 读取图片为base64 const base64String = await FileSystem.readAsStringAsync(localUri, { encoding: FileSystem.EncodingType.Base64, }); // 转换为Blob const blob = await fetch(`data:${type};base64,${base64String}`).then(res => res.blob()); // 构造FormData const formData = new FormData(); formData.append('file', blob, filename); // 这里直接传Blob对象
4. 检查iOS ATS配置(针对NGROK的HTTP连接)
如果你的NGROK隧道是HTTP协议,iOS的App Transport Security会阻止非HTTPS请求。需要在app.json里添加ATS配置:
{ "expo": { "ios": { "infoPlist": { "NSAppTransportSecurity": { "NSAllowsArbitraryLoads": true } } } } }
注意:如果是HTTPS隧道则不需要,但NGROK的免费版有时候会有证书缓存问题,可以重启NGROK隧道试试。
5. 验证服务器端的请求大小限制
虽然Postman能成功上传,但RN的请求可能因为某些隐式的头信息导致请求总大小触发服务器限制。检查你的后端服务(比如Nginx、Express等)是否设置了足够大的client_max_body_size或类似参数。
这些方法都是我在解决同类问题时验证有效的,你可以按顺序尝试,尤其是前两个方案,针对Expo iOS的路径问题非常有效。
内容的提问来源于stack exchange,提问作者user3055938

