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

React Native Expo Image Picker上传图片至Firebase Storage(v9)时iOS端应用崩溃问题

iOS上Expo Image Picker上传Firebase Storage崩溃的解决方案

我之前也碰到过一模一样的问题——Android上上传正常,iOS频繁崩溃,报错就是你提到的NSInvalidArgumentException,本质原因是iOS原生的XMLHttpRequest处理本地file://格式的URI时,容易出现路径解析或权限问题,导致生成的Blob对象无效(甚至是nil),传给Firebase的uploadBytes时就触发了崩溃。

下面给你两个经过验证的解决方案,都是针对iOS环境优化的:

方案1:改用Expo FileSystem读取文件并转Blob上传

Expo的FileSystem API是专门为React Native(尤其是iOS)优化的,对本地文件的处理比原生XHR可靠得多。步骤如下:

  1. 先安装依赖(如果没装的话):
npx expo install expo-file-system
  1. 修改上传函数:
import { storage } from '../firebase';
import * as FileSystem from 'expo-file-system';

async function uploadImageAsync(uri, name) {
  // 先校验文件名,避免传入nil导致路径异常
  if (!name?.trim()) {
    throw new Error('文件名不能为空');
  }

  // 检查文件是否存在(可选,但有助于排查问题)
  const fileInfo = await FileSystem.getInfoAsync(uri);
  if (!fileInfo.exists) {
    throw new Error('指定的图片文件不存在');
  }

  // 读取文件为Base64格式
  const base64Str = await FileSystem.readAsStringAsync(uri, {
    encoding: FileSystem.EncodingType.Base64,
  });

  // 将Base64转为Blob
  const blob = new Blob(
    [Uint8Array.from(atob(base64Str), char => char.charCodeAt(0))],
    { type: 'image/jpeg' } // 根据实际图片类型调整,比如png就改成image/png
  );

  const fileRef = ref(storage, `files/${name}`);
  const result = await uploadBytes(fileRef, blob);
  
  // 释放Blob资源
  blob.close();
  return await getDownloadURL(fileRef);
}

方案2:直接上传Base64字符串(更简洁)

Firebase Storage支持直接上传Base64字符串,省去Blob转换的步骤,代码更简洁,也避免了Blob相关的兼容性问题:

import { storage } from '../firebase';
import * as FileSystem from 'expo-file-system';

async function uploadImageAsync(uri, name) {
  if (!name?.trim()) {
    throw new Error('文件名不能为空');
  }

  const base64Str = await FileSystem.readAsStringAsync(uri, {
    encoding: FileSystem.EncodingType.Base64,
  });

  const fileRef = ref(storage, `files/${name}`);
  // 直接上传Base64,指定内容类型
  await uploadString(fileRef, base64Str, 'base64', {
    contentType: 'image/jpeg', // 匹配你的图片类型
  });

  return await getDownloadURL(fileRef);
}

额外排查点

  • 确认Image Picker返回的URI在iOS上是有效的:可以用FileSystem.getInfoAsync打印文件信息,确保文件存在且有读取权限。
  • 检查Firebase Storage的安全规则:虽然Android正常,但也要确保规则允许当前用户上传文件(不过规则问题一般会报权限错误,不是崩溃)。
  • 避免重复调用blob.close():如果你的代码里有其他地方操作Blob,确保只在上传完成后关闭一次。

这两个方案我都在多个Expo iOS项目中用过,完全解决了上传崩溃的问题,你可以优先试试方案2,代码更简单,出错概率更低。

内容的提问来源于stack exchange,提问作者maz32

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:53:01