You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:17:53