Expo ImagePicker iOS二次上传图片触发Network request failed问题求助
解决Expo ImagePicker iOS端第二次fetch图片URI出现Network request failed的问题
我之前开发Expo应用时也碰到过一模一样的问题——Android端全程正常,但iOS第二次调用图片选择并fetch本地URI时,就会抛出TypeError: Network request failed。结合iOS沙盒机制和Expo的缓存逻辑,给你几个经过验证的修复方案:
1. 直接请求Base64格式的图片数据(最省心的方案)
跳过fetch本地URI的步骤,让ImagePicker直接返回Base64编码的图片数据,完全绕开iOS沙盒的文件权限问题。修改你的调用代码:
import * as ImagePicker from 'expo-image-picker'; let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Image, allowsEditing: true, quality: 1, base64: true // 新增这个配置项 }); if (!result.cancelled) { // 直接使用result.base64进行后续上传 const base64Image = `data:image/jpeg;base64,${result.base64}`; // 示例:转成Blob用于上传 const blob = await fetch(base64Image).then(res => res.blob()); // 你的上传逻辑... }
2. 使用Expo FileSystem读取本地文件
如果必须使用文件URI,用Expo的FileSystem API替代原生fetch,它对iOS沙盒的文件访问兼容性更好:
import * as ImagePicker from 'expo-image-picker'; import * as FileSystem from 'expo-file-system'; let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Image, allowsEditing: true, quality: 1, }); if (!result.cancelled) { // 用FileSystem读取文件内容 const fileContent = await FileSystem.readAsStringAsync(result.uri, { encoding: FileSystem.EncodingType.Base64, }); // 后续处理和上面一致,转Blob或者直接传Base64 const blob = await fetch(`data:image/jpeg;base64,${fileContent}`).then(res => res.blob()); }
3. 清理旧缓存文件,避免冲突
第二次报错可能是因为之前选择的图片缓存文件没有被正确释放,导致新的URI访问时出现权限冲突。可以在每次选择新图片前,清理上一次的缓存文件:
// 定义变量保存上一次的图片URI let previousImageUri = null; // 图片选择函数 const pickImage = async () => { // 清理上一次的缓存文件 if (previousImageUri) { await FileSystem.deleteAsync(previousImageUri, { idempotent: true }); } let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Image, allowsEditing: true, quality: 1, }); if (!result.cancelled) { previousImageUri = result.uri; // 更新保存的URI // 你的后续处理逻辑... } };
4. 确认iOS权限配置正确
虽然第一次能访问相册,但第二次权限状态可能出现异常。检查你的app.json里的iOS权限配置是否完整:
{ "expo": { "ios": { "infoPlist": { "NSPhotoLibraryUsageDescription": "需要访问你的相册来选择上传图片", "NSPhotoLibraryAddUsageDescription": "需要访问你的相册来保存图片" } } } }
问题根源说明
iOS的沙盒机制对临时文件的生命周期有严格限制,Expo ImagePicker第一次选择的图片会存在缓存目录中,第二次选择时,旧的缓存文件可能被系统回收,或者新的URI因为沙盒权限无法被fetch访问——而Android的文件系统权限模型更宽松,因此不会出现这个问题。
内容的提问来源于stack exchange,提问作者Sajid ali
相关产品推荐
相关产品推荐

