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

React中XMLHttpRequestUpload的onprogress/loadend事件提前触发问题

问题解决思路

1. 服务器端请求缓冲是核心原因

大部分情况下,这种现象是因为服务器先缓存了整个请求体再处理,导致浏览器误以为上传已经完成(触发xhr.upload的进度和结束事件),但网络面板显示的是服务器后台处理文件的耗时,而非真实的上传耗时。

  • 若用Nginx做反向代理,需配置proxy_request_buffering off,禁止缓存请求体,让服务器实时接收文件块。
  • 后端框架也可能有类似的请求缓冲配置,比如Express的body-parser处理大文件时的设置,需调整为流式接收,而非一次性缓存。

2. 调整XHR事件绑定顺序

部分浏览器对时序敏感,建议把upload事件绑定放在xhr.open()之前,确保事件能被正确监听:

const uploadData = (method, url, data) => {
  const formData = new FormData();
  formData.append('file', data);
  const xhr = new XMLHttpRequest();

  // 先绑定upload相关事件
  xhr.upload.onprogress = (e) => console.log(`Uploaded:${e.loaded} of ${e.total}`);
  xhr.upload.onloadend = (e) => console.log('finished');

  xhr.open(method, url);

  return new Promise((resolve, reject) => {
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(xhr.response);
      } else {
        reject({
          status: xhr.status,
          statusText: xhr.statusText,
        });
      }
    };
    xhr.onerror = () => {
      reject({
        status: xhr.status,
        statusText: xhr.statusText,
      });
    };
    xhr.send(formData);
  });
};

3. 校验传入的文件对象

确保data参数是标准的File或Blob对象,非标准对象会导致XHR无法正确识别文件大小,直接触发100%进度:

const uploadData = (method, url, data) => {
  // 新增校验
  if (!(data instanceof File || data instanceof Blob)) {
    throw new Error('上传数据必须是File或Blob类型');
  }
  
  const formData = new FormData();
  formData.append('file', data);
  // 后续代码不变...
};

4. 排除外部干扰

  • 在浏览器无痕模式下测试,排除插件缓存的影响。
  • 关闭代理工具,避免代理服务器提前缓存请求体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:07:32