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

React Native中如何向Firebase Storage上传视频?

解决React Native中Firebase Storage上传视频报错"Expected Blob or File"的问题

你遇到的这个错误核心原因很明确:Firebase Web SDK的put()方法是为浏览器环境设计的,它期待接收Blob或File类型的对象,但React Native里的视频URI只是本地文件的路径字符串,无法直接被识别,所以才会抛出"Invalid argument"的错误。

下面给你两种可行的解决方案,优先推荐第一种,更适配React Native生态:


方案1:使用react-native-firebase的Storage模块(推荐)

react-native-firebase是Firebase官方为React Native打造的适配库,它的Storage模块专门提供了putFile()方法,直接支持本地文件URI,不需要额外做格式转换,是最省心的方案。

实现步骤:

  1. 如果你还没安装react-native-firebase,先按照官方指引完成安装和基础配置(重点确保Storage模块配置正确)。
  2. 修改你的上传函数为以下代码:
import storage from '@react-native-firebase/storage';

async function uploadVideo(uri) {
  console.log("inside");
  // 创建Storage存储引用
  const videoRef = storage().ref('images').child(`${Student.FirstName}`).child('video_098');
  
  try {
    // 直接传入视频URI启动上传任务
    const uploadTask = videoRef.putFile(uri, {
      contentType: 'video/mp4',
    });

    // 监听上传进度与状态变化
    uploadTask.on('state_changed', snapshot => {
      const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      console.log(`Upload is ${progress}% done`);
      
      switch (snapshot.state) {
        case storage.TaskState.PAUSED:
          console.log('Upload is paused');
          break;
        case storage.TaskState.RUNNING:
          console.log('Upload is running');
          break;
      }
    });

    // 等待上传完成,获取下载链接
    await uploadTask;
    const downloadURL = await videoRef.getDownloadURL();
    console.log('File available at', downloadURL);
  } catch (error) {
    console.error('Upload failed:', error);
    // 根据错误码处理不同场景
    switch (error.code) {
      case 'storage/unauthorized':
        alert('没有权限访问存储资源');
        break;
      case 'storage/canceled':
        console.log('用户取消了上传');
        break;
      default:
        alert('上传出错,请重试');
        break;
    }
  }
}

这个方案的优势是完全适配RN环境,不需要手动处理文件读取和格式转换,代码简洁且可靠性更高。


方案2:用rn-fetch-blob将本地文件转为Blob(适配Web SDK)

如果你不想切换SDK,坚持使用Firebase Web SDK,可以通过rn-fetch-blob读取本地文件并转换为Blob对象,再传给put()方法。

实现步骤:

  1. 先安装依赖:
npm install rn-fetch-blob --save
# 或者使用yarn
yarn add rn-fetch-blob
  1. 修改你的上传函数:
import RNFetchBlob from 'rn-fetch-blob';
import firebase from 'firebase/app';
import 'firebase/storage';
import { Platform } from 'react-native';

function uploadVideo(uri) {
  console.log("inside");
  const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
  const videoRef = firebase.storage().ref('images').child(`${Student.FirstName}`).child('video_098');
  
  // 读取本地文件为base64格式,再转换为Blob
  RNFetchBlob.fs.readFile(uploadUri, 'base64')
    .then(base64Data => {
      // 构建Blob对象
      const blob = RNFetchBlob.polyfill.Blob.build(base64Data, { type: 'video/mp4' });
      // 替换RN环境的Blob实现(RN原生没有浏览器的Blob对象)
      window.Blob = RNFetchBlob.polyfill.Blob;

      const metadata = { contentType: 'video/mp4' };
      const uploadTask = videoRef.put(blob, metadata);

      // 监听上传状态(和你原来的逻辑一致)
      uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, 
        snapshot => {
          const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
          console.log(`Upload is ${progress}% done`);
          switch (snapshot.state) {
            case firebase.storage.TaskState.PAUSED:
              console.log('Upload is paused');
              break;
            case firebase.storage.TaskState.RUNNING:
              console.log('Upload is running');
              break;
          }
        }, 
        error => {
          console.error('Upload error:', error);
          switch (error.code) {
            case 'storage/unauthorized':
              // 处理权限问题
              break;
            case 'storage/canceled':
              // 处理取消上传
              break;
            case 'storage/unknown':
              // 未知错误,可查看error.serverResponse详情
              break;
          }
        }, 
        () => {
          // 上传完成,获取下载链接
          uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
            console.log('File available at', downloadURL);
            // 记得关闭Blob释放资源
            blob.close();
          });
        }
      );
    })
    .catch(err => {
      console.error('Failed to read local file:', err);
    });
}

这种方法需要手动处理Blob的创建和环境polyfill,适合坚持使用Web SDK的场景,但相对方案1会繁琐一些。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:42:39