React Native使用fetch API发送文件时遇网络请求失败错误求助
解决React Native 0.80.2中fetch发送FormData文件报Network request failed的问题
核心问题分析
直接用JSON.stringify(form)虽然能消除错误,但本质是把FormData转成了普通JSON字符串,服务器无法识别multipart/form-data格式,自然接收不到文件。必须保持body: form的方式,针对以下常见问题排查:
1. 检查文件URI格式是否正确
React Native中iOS和Android的文件URI规则不同,错误的URI会导致网络请求失败:
- iOS:确保URI以
file://开头,从相册/相机获取的URI通常符合要求,自定义路径需验证文件实际存在。 - Android:避免使用
content://开头的媒体库URI,需转换为真实文件路径。可借助react-native-fs库处理,示例:import RNFS from 'react-native-fs'; // 转换content URI为真实路径 const statResult = await RNFS.stat(uri); const realFileUri = `file://${statResult.path}`; // 构造FormData字段 form.append('audio', { uri: realFileUri, name, type: mime });
2. 不要手动设置错误的Content-Type
当body为FormData时,fetch会自动生成带boundary的Content-Type: multipart/form-data请求头。手动指定完整的Content-Type(比如加charset或boundary)会覆盖自动配置,导致请求失败。如果必须设置,仅保留类型即可:
const res = await fetch(`${URL}/api/endpoint`, { method: 'POST', body: form, headers: { 'Content-Type': 'multipart/form-data' } });
3. 验证文件访问权限
- Android:在
AndroidManifest.xml中添加对应权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 需额外添加 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> - iOS:在
Info.plist中添加权限描述(以访问相册为例):<key>NSPhotoLibraryUsageDescription</key> <string>需要访问相册以选择音频文件</string>
4. 检查测试环境网络配置
- Android模拟器访问本地服务器时,需用
10.0.2.2代替localhost;iOS模拟器可直接用localhost或电脑IP。 - 确保设备/模拟器和服务器在同一局域网内,且服务器端口未被防火墙拦截。
修正后的完整代码示例
import RNFS from 'react-native-fs'; import { Platform } from 'react-native'; const uploadAudio = async (uri, name, mime, fieldName) => { let fileUri = uri; // 处理Android的content URI if (Platform.OS === 'android' && uri.startsWith('content://')) { const statResult = await RNFS.stat(uri); fileUri = `file://${statResult.path}`; } const form = new FormData(); form.append('audio', { uri: fileUri, name, type: mime }); form.append('fieldName', fieldName); try { const res = await fetch(`${URL}/api/endpoint`, { method: 'POST', body: form }); const responseData = await res.json(); console.log('上传成功:', responseData); } catch (error) { console.error('上传失败:', error); } };
内容的提问来源于stack exchange,提问作者ray
相关产品推荐
相关产品推荐

