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

React Native Expo Base64图片任意方法均无法上传至Firebase Storage

React Native Expo 环境Base64图片上传Firebase Storage落地指南

你遇到的所有报错本质是三个核心问题:全局polyfill写法不兼容RN JS引擎导致崩溃、data URI拼接错误触发Firebase格式校验、RN原生网络栈不支持解析data协议URI导致fetch/XHR转Blob失败。下面是经过验证的可运行方案,按步骤来就行。

前置修正:先处理基础数据错误

你之前展示图片用的URI拼接少了关键的逗号,这是格式报错的核心诱因之一,Firebase对上传字符串的格式校验非常严格,容错率远低于Image组件。
首先清洗expo-camera返回的base64数据,部分机型返回的base64会夹带换行、空格等非法字符:

// 拍照配置不需要改
const photo = await camera.takePictureAsync({
  quality: 1,
  base64: true,
  exif: false
})

// 清洗base64,移除所有空白字符
const pureBase64 = photo.base64.replace(/\s/g, '')
// 拼接完整data URL,注意base64后面必须加逗号
const dataUrl = `data:image/jpeg;base64,${pureBase64}`

方案一:用uploadString上传(最稳定,代码量最少,优先选)

不要安装第三方base-64包做全局polyfill,第三方包和RN的Hermes引擎兼容性很差,很容易直接崩溃。Firebase依赖的abort-controller包Expo环境默认自带,直接用里面的atob/btoa做polyfill即可,不会有兼容问题。
在项目入口文件(App.js/index.js)的最顶部添加以下polyfill代码,放在所有import的最前面:

// 不需要额外安装依赖,项目自带
import { atob, btoa } from 'abort-controller/dist/abort-controller'
global.atob = atob
global.btoa = btoa

上传逻辑直接用拼接好的完整dataUrl,格式参数指定为data_url,不要传纯base64字符串:

import { getStorage, ref, uploadString, getDownloadURL } from 'firebase/storage'
const storage = getStorage()
// 自定义存储路径,建议加时间戳避免重名
const storageRef = ref(storage, `camera_upload/${Date.now()}.jpg`)

const snapshot = await uploadString(storageRef, dataUrl, 'data_url')
const downloadUrl = await getDownloadURL(snapshot.ref)
console.log('上传成功,图片访问地址:', downloadUrl)

方案二:用uploadBytes传Blob(如果业务必须用Blob格式)

不要用fetch、XMLHttpRequest去请求data://开头的URI,RN的网络栈不识别data协议,会把URI当成本地文件路径查找,必然报ENOENT找不到文件的错误。
如果必须传Blob,直接读拍照返回的本地临时文件(就是photo.uri字段,根本不需要用base64转,开base64反而会占用大量内存容易OOM),用expo-file-system做转换:
首先安装依赖(如果没装的话):

npx expo install expo-file-system

转换+上传代码:

import * as FileSystem from 'expo-file-system'
import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage'

const storage = getStorage()
const storageRef = ref(storage, `camera_upload/${Date.now()}.jpg`)

// 直接读本地拍照临时文件,不需要走base64
const base64Data = await FileSystem.readAsStringAsync(photo.uri, {
  encoding: FileSystem.EncodingType.Base64
})
// 转Blob
const blob = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0))
// 上传
const snapshot = await uploadBytes(storageRef, blob, { contentType: 'image/jpeg' })
const downloadUrl = await getDownloadURL(snapshot.ref)
console.log('上传成功,图片访问地址:', downloadUrl)

避坑清单

  • 不要用第三方base-64包做全局polyfill,90%的崩溃问题都是这个导致的
  • 拼接data URL时base64,的逗号绝对不能漏,漏了必然报格式非法
  • 拍照时如果不需要直接拿base64做业务处理,建议把base64:true关掉,直接用photo.uri本地上传,内存占用能降80%以上,大幅减少崩溃概率
  • 不要尝试用fetch/XHR请求data开头的URI,RN环境下这个路径走不通
  • 上传时如果是jpg格式,contentType统一写image/jpeg,不要写image/jpg,后者不是标准MIME类型,部分场景下会导致Firebase返回的图片无法直接预览

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:15:34