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

React Native Expo 上传文件到 Firebase Storage 出现网络请求失败如何解决?

问题描述

我在使用 Expo 开发 React Native 应用,尝试将文件上传到 Firebase Storage 时触发了警告,相关代码与报错信息如下:

设备文件选取函数

const pickDocument = async () => {
    let result = await DocumentPicker.getDocumentAsync({
      // type: "application/pdf",
    });

    if (result != null) {
      setfile(result);
      setfileName(result.name);
      seturi(result.uri);
      console.log(result);
    }
  };

文件上传函数

const uploadLessonSlide = async (uri) => {
    const blob = await new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.onload = function () {
        resolve(xhr.response);
      };
      xhr.onerror = function (e) {
        console.log("error");
        console.log(e);

        reject(new TypeError("Network request failed"));
      };
      xhr.responseType = "blob";
      xhr.open("GET", uri, true);
      xhr.send(null);
    });

    const ref = storage.ref().child("images");
    const snapshot = await ref.put(blob);

    blob.close();

    return await snapshot.ref.getDownloadURL();
  };

报错信息

控制台警告

[Unhandled promise rejection: TypeError: Network request failed]
at node_modules/react-native/Libraries/Network/XMLHttpRequest.js:600:10 in setReadyState
at node_modules/react-native/Libraries/Network/XMLHttpRequest.js:395:6 in __didCompleteResponse
at node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10 in emit

文件选择器输出结果

Object {
  "name": "sinhala-nisadas-10.jpg",
  "size": 19346,
  "type": "success",
  "uri": "/data/user/0/host.exp.exponent/cache/ExperienceData/%40shehan82%2FschoolyMobNative/DocumentPicker/97a75d14-1b7f-468b-aeae-59a6e65aa96b.jpg",
}

xhr.onerror捕获的错误信息

Event {
  "isTrusted": false,
}

相关截图

上传函数代码
文件选取函数代码
文件选择器输出与警告信息

问题原因与解决方案

原因

你拿到的文件uri是Expo沙盒的本地绝对路径,缺少file://协议头,XMLHttpRequest无法识别该类无协议的本地路径,触发请求失败错误。

解决方案

核心修复:补全本地文件uri协议头

在使用uri前判断是否已经带有file://前缀,没有的话主动拼接,修改后的上传函数如下:

const uploadLessonSlide = async (uri) => {
  // 补全本地文件协议头,避免重复拼接
  const fileUri = uri.startsWith('file://') ? uri : `file://${uri}`
  const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      console.log("error");
      console.log(e);
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", fileUri, true);
    xhr.send(null);
  });

  // 建议给存储文件添加唯一命名,避免重名覆盖
  const ref = storage.ref().child(`images/${Date.now()}_${fileName}`);
  const snapshot = await ref.put(blob);

  blob.close();

  return await snapshot.ref.getDownloadURL();
};

额外优化

  • 上传逻辑外层添加try/catch捕获异常,避免出现未处理的Promise rejection警告
  • 若无需兼容旧版本逻辑,可以用fetch API替代XHR,写法更简洁:
const uploadLessonSlide = async (uri) => {
  const fileUri = uri.startsWith('file://') ? uri : `file://${uri}`
  const blob = await fetch(fileUri).then(res => res.blob())
  const ref = storage.ref().child(`images/${Date.now()}_${fileName}`);
  const snapshot = await ref.put(blob);
  blob.close();
  return await snapshot.ref.getDownloadURL();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:54:04