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

Expo+Firebase上传图片报错:为何仅支持Blob转Blob而非Uint8Array?

解决Expo + Firebase Storage上传图片的Blob兼容性问题

嘿,我之前也踩过这个Expo + Firebase Storage的坑!这个报错的根源其实是React Native(包括Expo)环境里的Blob实现和标准Web环境不一样,Firebase JS SDK原本是为Web设计的,它内部创建Blob的逻辑只认它能识别的Blob类型,直接用Uint8Array转换时就会抛出那个“Can currently only create a Blob from other Blobs”的错误。

下面给你两个靠谱的解决办法:

方法一:改用Base64格式上传(最简单高效)

Expo的FileSystem可以直接把图片读取为Base64,然后用Firebase的uploadString方法上传,完全绕开Blob兼容性问题,这也是我现在常用的方式:

import * as ImagePicker from 'expo-image-picker';
import { getStorage, ref, uploadString } from "firebase/storage";
import * as FileSystem from 'expo-file-system';

const pickAndUploadImage = async () => {
  // 先申请图片访问权限
  const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
  if (status !== 'granted') {
    alert('需要开启图片权限才能继续操作哦');
    return;
  }

  // 调用ImagePicker选择图片
  const pickerResult = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    allowsEditing: true,
    quality: 0.8, // 控制图片质量,平衡大小和清晰度
  });

  if (!pickerResult.canceled) {
    // 把选中的图片读取为Base64字符串
    const base64Image = await FileSystem.readAsStringAsync(pickerResult.assets[0].uri, {
      encoding: FileSystem.EncodingType.Base64,
    });

    // 上传到Firebase Storage
    const storage = getStorage();
    const imageRef = ref(storage, `user-uploads/${Date.now()}.jpg`); // 自定义存储路径和文件名
    const uploadSnapshot = await uploadString(imageRef, base64Image, 'base64', {
      contentType: 'image/jpeg', // 指定文件MIME类型
    });

    console.log('图片上传成功!存储路径:', uploadSnapshot.ref.fullPath);
  }
};

方法二:用rn-fetch-blob创建兼容的Blob(如果坚持用Uint8Array)

如果你一定要用Uint8Array的方式,那得用rn-fetch-blob提供的Blob构造函数来创建实例,Firebase SDK能识别这个Blob类型:

import RNFetchBlob from 'rn-fetch-blob';
import { getStorage, ref, uploadBytes } from "firebase/storage";
import * as ImagePicker from 'expo-image-picker';

const pickAndUploadImage = async () => {
  // 权限申请和图片选择步骤和上面一致
  const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
  if (status !== 'granted') {
    alert('需要开启图片权限才能继续操作哦');
    return;
  }

  const pickerResult = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    allowsEditing: true,
    quality: 0.8,
  });

  if (!pickerResult.canceled) {
    // 读取图片为Base64,再转换为Uint8Array
    const base64Data = await RNFetchBlob.fs.readFile(pickerResult.assets[0].uri, 'base64');
    const uint8Array = new Uint8Array(atob(base64Data).split('').map(char => char.charCodeAt(0)));

    // 用rn-fetch-blob的Blob构造函数创建兼容的Blob实例
    const compatibleBlob = RNFetchBlob.polyfill.Blob.build(uint8Array, { type: 'image/jpeg' });

    // 上传到Firebase Storage
    const storage = getStorage();
    const imageRef = ref(storage, `user-uploads/${Date.now()}.jpg`);
    const uploadSnapshot = await uploadBytes(imageRef, compatibleBlob);

    console.log('图片上传成功!存储路径:', uploadSnapshot.ref.fullPath);
    compatibleBlob.close(); // 记得关闭Blob释放资源
  }
};

核心原因再强调下:Firebase JS SDK的Blob处理逻辑是针对Web标准Blob写的,而RN/Expo里的全局Blob是平台特定的实现,和标准Blob不兼容,所以要么绕开Blob用Base64,要么用rn-fetch-blob提供的兼容Blob类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:27:50