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

Expo项目使用uploadBytesResumable上传Firebase Storage图片时随机崩溃

问题

我开发了一个Expo项目,需要将用户头像上传至Firebase Storage。除图片上传外其余功能均正常,但上传时会随机崩溃,无任何错误提示。该问题在iOS和Android的模拟器及真机上均会出现,崩溃发生在上传进度18%-80%之间。

相关代码如下:

import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";

const uploadImage = async (theImage) => {
        const response = await fetch(theImage);
        const file = await response.blob();
        const storageRef = ref(storage, `images/${signedUser.uid}`);
        const uploadTask = uploadBytesResumable(storageRef, file);

        // Listen for state changes, errors, and completion of the upload.
        uploadTask.on('state_changed',
        (snapshot) => {
            // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
            const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
            console.log('Upload is ' + progress + '% done');
            switch (snapshot.state) {
            case 'paused':
                console.log('Upload is paused');
                break;
            case 'running':
                console.log('Upload is running');
                break;
            }
        }, 
        (error) => {
            console.log("Error: ", error.message)
        }, 
        () => {
            // Upload completed successfully, now we can get the download URL
            getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
                /*console.log('File available at', downloadURL);
                navigation.navigate({
                    name: 'Perfil',
                    params: { changed: true },
                    merge: true,
                  });*/
                navigation.goBack();
            });
        }
        );
}
解决方案
  • 优化Blob处理,避免内存溢出
    Expo中通过fetch转Blob处理大图片时,容易出现内存问题。改用Expo提供的FileSystem模块读取文件为base64,再转成Uint8Array上传,减少内存占用:

    import * as FileSystem from 'expo-file-system';
    
    const uploadImage = async (theImage) => {
      const base64 = await FileSystem.readAsStringAsync(theImage, { encoding: FileSystem.EncodingType.Base64 });
      const uint8Array = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
      const storageRef = ref(storage, `images/${signedUser.uid}`);
      const uploadTask = uploadBytesResumable(storageRef, uint8Array);
      // 后续监听逻辑不变
    }
    
  • 完善错误捕获与全局异常监听
    当前错误回调只打印error.message,很多原生崩溃不会触发这个回调。在uploadBytesResumable外层包裹try-catch,同时添加全局异常监听:

    const uploadImage = async (theImage) => {
      try {
        // 原上传逻辑
      } catch (e) {
        console.error('全局捕获错误:', e);
      }
    }
    // 全局监听(可放在App.js中)
    import * as ErrorRecovery from 'expo-error-recovery';
    ErrorRecovery.setRecoveryProps({ lastAction: 'upload-image' });
    
  • 限制上传图片的尺寸与质量
    大尺寸头像会导致上传过程中内存占用过高崩溃,上传前用Expo的ImageManipulator压缩图片:

    import * as ImageManipulator from 'expo-image-manipulator';
    
    const compressImage = async (uri) => {
      const result = await ImageManipulator.manipulateAsync(
        uri,
        [{ resize: { width: 800 } }], // 限制宽度为800px
        { compress: 0.7, format: ImageManipulator.SaveFormat.JPEG }
      );
      return result.uri;
    }
    
    // 在uploadImage中先压缩
    const compressedUri = await compressImage(theImage);
    // 再用compressedUri处理上传
    
  • 确保上传任务的生命周期绑定
    组件卸载时取消未完成的上传任务,避免内存泄漏导致崩溃:

    import { useEffect, useRef } from 'react';
    
    const YourComponent = () => {
      const uploadTaskRef = useRef(null);
    
      const uploadImage = async (theImage) => {
        // ...原逻辑
        uploadTaskRef.current = uploadTask;
      }
    
      useEffect(() => {
        return () => {
          if (uploadTaskRef.current) {
            uploadTaskRef.current.cancel();
          }
        };
      }, []);
    
      // ...其他组件逻辑
    }
    
  • 更新依赖版本
    检查并更新firebase、expo相关依赖到最新稳定版,部分旧版本存在已知的上传崩溃bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:01:19