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

ReactJS结合Firebase上传图片时如何显示上传进度提示?

实现方法

Firebase Storage的上传任务原生支持进度监听,配合全屏遮罩+页面离开拦截就能实现你要的效果,不需要引入额外依赖。

1. 添加上传状态视觉提示

先在页面中插入一个默认隐藏的全屏遮罩层,上传开始时显示,上传结束(成功/失败)时隐藏,层内放置加载图标、进度条、进度文字即可。因为遮罩层级最高,会覆盖页面所有可点击元素,自然能阻止用户上传过程中点击页面内的按钮、链接跳转。
基础遮罩结构示例:

<div id="upload-mask" style="display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: 9999; flex-direction: column; justify-content: center; align-items: center;">
  <!-- 转圈加载图标,可自行替换成项目里的加载组件 -->
  <div class="spin-icon" style="width: 40px; height: 40px; border: 4px solid #fff; border-top-color: transparent; border-radius: 50%; animation: spin 1s linear infinite;"></div>
  <div style="width: 300px; height: 8px; background: #eee; border-radius: 4px; margin: 20px 0; overflow: hidden;">
    <div id="progress-bar" style="height: 100%; width: 0; background: #2563eb; transition: width .2s;"></div>
  </div>
  <p id="progress-text" style="color: #fff; margin: 0;">上传中 0%</p>
</div>
<style>
@keyframes spin {to {transform: rotate(360deg);}}
</style>

2. 修改上传逻辑,监听进度+拦截页面关闭

用Firebase上传任务自带的state_changed观察者实时获取上传进度,同时监听浏览器的beforeunload事件,阻止用户上传过程中刷新、关闭标签页、跳转到外部站点。
修改后的完整上传代码:

// 提前获取遮罩相关DOM元素
const uploadMask = document.getElementById('upload-mask');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');

const uploadToFirebase = e => {
  e.preventDefault();
  if (!image) {
    alert("Please upload an image first.");
    return;
  }

  // 初始化上传状态:显示遮罩、重置进度
  uploadMask.style.display = 'flex';
  progressBar.style.width = '0%';
  progressText.textContent = '上传中 0%';

  // 监听页面关闭/跳转事件
  const preventLeave = (e) => {
    e.preventDefault();
    e.returnValue = '文件正在上传,确定离开当前页面吗?';
    return e.returnValue;
  };
  window.addEventListener('beforeunload', preventLeave);

  const storageRef = storage.ref(`${user1}/${tripid}/documents`);
  const imageRef = storageRef.child(image.name);
  const uploadTask = imageRef.put(image);

  uploadTask.on('state_changed',
    // 进度更新回调
    (snapshot) => {
      const percent = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
      progressBar.style.width = `${percent}%`;
      progressText.textContent = `上传中 ${percent}%`;
    },
    // 上传失败回调
    (err) => {
      window.removeEventListener('beforeunload', preventLeave);
      uploadMask.style.display = 'none';
      alert(`上传失败:${err.message}`);
    },
    // 上传完成回调
    () => {
      window.removeEventListener('beforeunload', preventLeave);
      uploadMask.style.display = 'none';
      alert("Successfully uploaded.");
      getFromFirebase();
    }
  );
};

注意事项

  • 无论上传成功还是失败,一定要移除beforeunload事件监听、隐藏遮罩层,避免上传结束后用户仍无法正常操作页面
  • 如果项目用的是React/Vue等框架,把DOM操作换成框架对应的状态绑定即可,核心逻辑不变
  • 遮罩层不要加关闭按钮,强制用户等待上传完成

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:03:19