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

使用Expo拍摄的照片通过Firebase JS SDK上传至Firebase Storage失败(Blob转换问题)

Expo拍摄的照片通过Firebase JS SDK上传至Firebase Storage失败(Blob转换问题)

Hey there, I totally get the frustration here—Expo Go on Android has some quirks with blob handling that don’t pop up on web, and sticking to the Firebase JS SDK for cross-platform consistency makes total sense. Let’s break down how to fix this blob conversion and get your photos uploading smoothly.

核心问题:Expo Camera的照片格式在Android上的特殊性

On Android, the takePictureAsync method returns a photo object with a uri that points to a local file, but converting that directly to a blob doesn’t work the same way as it does on web. The base64 string is there, but we need to handle it properly, or use the local file URI with a fetch that’s compatible with Expo’s file system.

解决方案1:使用Base64字符串上传(简单直接,兼容Web+Android)

Since you’re already capturing base64, we can use Firebase’s uploadString method which handles this natively, no blob conversion needed. Here’s how to adjust your takePhoto function:

const takePhoto = async () => {
  const photo = await cameraRef.current?.takePictureAsync({
    quality: 0.5,
    base64: true,
  });

  if (!photo || !photo.base64) {
    console.error('No photo or base64 data found');
    return;
  }

  try {
    // Create a reference to your Firebase Storage location
    const storageRef = getStorage();
    const photoRef = ref(storageRef, `photos/${Date.now()}.jpg`);

    // Upload the base64 string as a JPEG
    const snapshot = await uploadString(
      photoRef,
      photo.base64,
      'base64',
      { contentType: 'image/jpeg' }
    );

    // Get the download URL if needed
    const downloadURL = await getDownloadURL(snapshot.ref);
    console.log('Photo uploaded successfully! URL:', downloadURL);
  } catch (error) {
    console.error('Upload failed:', error);
  }
};

This works because uploadString accepts base64 directly, skipping the blob conversion step that’s causing issues on Android. We specify the content type as image/jpeg to ensure Firebase stores it correctly.

解决方案2:正确转换本地URI为Blob(如果必须用Blob上传)

If you prefer using uploadBytes or uploadBytesResumable, you need to fetch the local file properly using Expo’s FileSystem module (since the standard fetch might not access the Expo Go file system correctly on Android). First, install it if you haven’t:

npx expo install expo-file-system

Then adjust your takePhoto function like this:

import * as FileSystem from 'expo-file-system';

const takePhoto = async () => {
  const photo = await cameraRef.current?.takePictureAsync({
    quality: 0.5,
    // base64 is optional here if we use the URI
  });

  if (!photo || !photo.uri) {
    console.error('No photo or URI found');
    return;
  }

  try {
    // Read the file as a base64 string first, then convert to blob
    const base64String = await FileSystem.readAsStringAsync(photo.uri, {
      encoding: FileSystem.EncodingType.Base64,
    });

    // Convert base64 to blob
    const blob = await fetch(`data:image/jpeg;base64,${base64String}`).then(res => res.blob());

    // Upload the blob
    const storageRef = getStorage();
    const photoRef = ref(storageRef, `photos/${Date.now()}.jpg`);
    const snapshot = await uploadBytes(photoRef, blob, { contentType: 'image/jpeg' });

    const downloadURL = await getDownloadURL(snapshot.ref);
    console.log('Photo uploaded successfully! URL:', downloadURL);
  } catch (error) {
    console.error('Upload failed:', error);
  }
};

The key here is using expo-file-system to read the local file into a base64 string, then converting that to a blob via a data URL fetch. This bypasses the Android-specific file access issues that come with trying to fetch the photo.uri directly.

额外注意事项

  • Make sure your Firebase Storage rules allow uploads (even in emulated mode, double-check the rules to avoid permission errors).
  • On Android, ensure you’ve requested the necessary permissions for camera and storage (you can use Expo’s permission utilities to handle this).
  • If you’re using the Firebase emulator, confirm that your physical Android device is on the same network as the emulator host, and that your app is configured to connect to the correct host address.

备注:内容来源于stack exchange,提问作者robsteward

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 12:59:42