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

React Native Expo中不使用Blob上传图片至Firebase Storage的方案

解决iOS上Firebase Storage上传图片体积变大的替代方案

针对你遇到的iOS平台用Blob上传图片体积变为四倍的问题,以下是几个无需依赖Blob的替代上传方案,以及修复原Blob方案的思路:

方案一:通过Expo Filesystem读取文件为Uint8Array上传

利用Expo Filesystem直接读取本地图片文件为Base64,再转换为Uint8Array后上传,避免Blob的编码问题:

import * as FileSystem from 'expo-file-system';
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import { v4 as uuidv4 } from 'uuid';

const uploadImage = async (picture) => {
  const randomId = uuidv4();
  
  // 读取本地文件为Base64格式
  const base64Str = await FileSystem.readAsStringAsync(picture, {
    encoding: FileSystem.EncodingType.Base64,
  });
  
  // 将Base64转换为Uint8Array
  const uint8Array = Uint8Array.from(atob(base64Str), char => char.charCodeAt(0));

  const path = `images/${randomId}`;
  const storage = getStorage();
  const metadata = { contentType: "image/jpeg" };
  const imagesRef = ref(storage, path);
  const uploadTask = uploadBytesResumable(imagesRef, uint8Array, metadata);

  // 上传状态监听逻辑与原代码一致
  uploadTask.on(
    "state_changed",
    (snapshot) => {
      const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      console.log(`Upload: ${progress}%`);
      switch (snapshot.state) {
        case "paused":
          console.log("Upload is paused");
          break;
        case "running":
          console.log("Upload is running");
          break;
      }
    },
    (error) => {
      console.log("Error uploading document: ", error);
    },
    () => {
      getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
        console.log("File available at", downloadURL);
      });
    }
  );
};

方案二:利用Expo Image Manipulator直接输出Base64上传

既然已经使用expo-image-manipulator处理图片,可以在处理阶段直接获取Base64数据,省去二次读取文件的步骤:

import * as ImageManipulator from 'expo-image-manipulator';
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import { v4 as uuidv4 } from 'uuid';

const processAndUploadImage = async (originalPicturePath) => {
  // 处理图片时直接输出Base64
  const manipulatedResult = await ImageManipulator.manipulateAsync(
    originalPicturePath,
    [{ resize: { width: 800 } }], // 你的缩放规则
    { 
      base64: true, 
      format: ImageManipulator.SaveFormat.JPEG, 
      quality: 0.8 // 可根据需求调整画质,平衡体积与清晰度
    }
  );

  const randomId = uuidv4();
  // 将Base64转换为Uint8Array
  const uint8Array = Uint8Array.from(atob(manipulatedResult.base64), char => char.charCodeAt(0));

  const path = `images/${randomId}`;
  const storage = getStorage();
  const metadata = { contentType: "image/jpeg" };
  const imagesRef = ref(storage, path);
  const uploadTask = uploadBytesResumable(imagesRef, uint8Array, metadata);

  // 后续监听逻辑与原代码一致
  uploadTask.on(
    "state_changed",
    (snapshot) => {
      const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      console.log(`Upload: ${progress}%`);
      switch (snapshot.state) {
        case "paused":
          console.log("Upload is paused");
          break;
        case "running":
          console.log("Upload is running");
          break;
      }
    },
    (error) => {
      console.log("Error uploading document: ", error);
    },
    () => {
      getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
        console.log("File available at", downloadURL);
      });
    }
  );
};

方案三:修复原Blob上传方案的编码问题

如果想继续使用Blob上传,可以手动指定Blob的MIME类型,避免iOS上自动识别错误导致的体积膨胀:

const picture = "file:///file/path";
const randomId = uuidv4();
const response = await fetch(picture);
const arrayBuffer = await response.arrayBuffer();
// 手动指定Blob的类型为image/jpeg,避免自动识别错误
const blob = new Blob([arrayBuffer], { type: "image/jpeg" });

const path = `images/${randomId}`;
const storage = getStorage();
const metadata = { contentType: "image/jpeg" };
const imagesRef = ref(storage, path);
const uploadTask = uploadBytesResumable(imagesRef, blob, metadata);

// 监听逻辑与原代码一致

以上方案中,方案一和方案二更适合Expo环境,能有效避免Blob在iOS上的编码问题;方案三则是对原有逻辑的最小修改,可快速验证是否解决体积问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:07:45