Expo v48及以上版本如何将本地图片添加到FormData?
Expo v48/v49 下 FormData 上传图片问题解决
问题背景
Expo v47 及对应 React Native、TypeScript 版本中,FormData.append 的类型定义宽松,允许传入任意类型值:
FormData.append(name: string, value: any): void
当时可直接通过自定义图片对象完成上传:
const image = { uri: x.uri, name: x.name, size: x.size, type: 'image/jpeg', } const formDataBody = new FormData() formDataBody.append('data', image)
升级到 Expo v48/v49 后,FormData.append 的类型定义收紧,仅接受字符串或 Blob 类型:
FormData.append(name: string, value: string | Blob): void
尝试过的方法及遇到的问题
- 转 base64 再生成 File 对象上传,触发网络错误:
try { base64String = await FileSystem.readAsStringAsync(image.uri, { encoding: 'base64' }) } catch (error: any) { // ... } const binaryData = decode(base64String) const buffer = new Uint8Array(binaryData.length) for (let i = 0; i < binaryData.length; i++) { buffer[i] = binaryData.charCodeAt(i) } const file = new File([binaryData], 'data', { type: 'image/jpeg' }) formDataBody.append('data', file)
- 尝试使用 react-native-fs 模块,出现启动错误:
ERROR Invariant Violation: "main" has not been registered. This can happen if: Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project. A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes
解决方案
方案1:通过 Expo FileSystem 获取 Blob 上传
这是最可靠的原生兼容方案,无需复杂转换:
import * as FileSystem from 'expo-file-system'; // 从本地URI获取Blob对象 const getImageBlob = async (uri: string) => { const response = await fetch(uri); return response.blob(); }; // 构建FormData const formDataBody = new FormData(); const blob = await getImageBlob(image.uri); // 第三个参数指定文件名,确保服务端能正确识别 formDataBody.append('data', blob, image.name);
原理:React Native 支持通过 fetch 本地文件 URI 直接获取 Blob,避免 base64 转换带来的编码错误和性能损耗。
方案2:类型断言绕过TS检查(仅兼容旧服务端)
如果后端仍支持原上传格式,可通过类型断言绕过 TypeScript 的类型限制:
const image = { uri: x.uri, name: x.name, type: 'image/jpeg', }; const formDataBody = new FormData(); // 用类型断言绕过TS类型检查 formDataBody.append('data', image as unknown as Blob);
注意:此方案依赖 RN 运行时的 FormData 实现仍支持自定义对象,部分新版本可能已移除该支持,需自行验证。
解决 react-native-fs 启动错误
若必须使用该模块:
- 确保 Metro 服务在项目根目录启动,执行
npx expo start --clear清除缓存后重启 - 确认 react-native-fs 版本与 Expo v48/v49 兼容,优先使用官方的
expo-file-system替代第三方模块,减少兼容性问题
内容的提问来源于stack exchange,提问作者Robert Pulkka
相关产品推荐
相关产品推荐

