必须用 xmlhttprequest.upload.onprogress 实时计算上传速度,因 fetch 无原生上传进度事件;常见错误包括漏写 .upload、file:// 协议限制、服务端缺失 content-length 或表单字段名不匹配;瞬时速度需基于 Δbytes/Δt 计算并节流更新。

必须用 XMLHttpRequest.upload.onprogress,不是 fetch
想实时算上传速度,fetch 基本没法直接做——它没有原生的上传进度事件。你得用 XMLHttpRequest,而且关键点是监听它的 upload 属性上的 onprogress,不是 xhr.onprogress(后者是下载用的)。漏掉 .upload 这一层,事件根本不会触发。
常见错误现象:onprogress 完全不执行,或 event.loaded 一直是 0。大概率是因为:
- 用了
file://协议本地双击打开 HTML —— 浏览器会禁掉XMLHttpRequest的跨域/上传能力,必须跑在http://或https://下 - 服务端没返回
Content-Length响应头(比如 Nginx 默认不透传),导致event.lengthComputable === false,event.total为 0 - 后端用了 multipart 解析但字段名(如
'file')和前端formData.append()不一致,上传被静默截断
onprogress 里怎么算瞬时速度
不能只靠单次 event.loaded 除以 event.total——那是进度,不是速度。速度得看单位时间内的字节数变化。
实操建议:
- 定义两个变量:
let lastLoaded = 0; let lastTime = 0; - 在
onprogress回调里,先检查if (event.lengthComputable),否则跳过 - 拿到当前
event.loaded和Date.now(),和上一次记录的值相减,得出 Δbytes 和 Δms - 速度(B/s)=
Δbytes / (Δms / 1000);换算成 KB/s 就再除以 1024 - 别每毫秒都算——加个节流,比如至少间隔 500ms 才更新一次显示,避免抖动太大
示例片段:
let lastLoaded = 0;
let lastTime = 0;
xhr.upload.onprogress = (e) => {
if (!e.lengthComputable) return;
const now = Date.now();
if (now - lastTime ${speedKBps} KB/s;
lastLoaded = e.loaded;
lastTime = now;
};
为什么上传速度经常“跳变”或归零
这不是代码 bug,而是网络传输本身的特性。上传速度受多个动态因素影响:
- TCP 拥塞控制:浏览器底层会根据丢包、延迟自动调整发送窗口,造成速度阶梯式升降
- 服务端接收瓶颈:如果后端写磁盘慢、IO 阻塞或解析 multipart 耗 CPU,会拖慢 ACK 返回,前端感知为“卡住”
- 浏览器限速策略:Chrome 对同一域名并发连接数有限制(通常 6 个),若页面还有其他请求,上传带宽会被抢占
- 小文件干扰:文件小于几 KB 时,TCP 握手+TLS 开销占比过大,测出的速度毫无参考价值,建议测试用 ≥1MB 文件
所以实际产品中,不要只显示瞬时值。可以缓存最近 3–5 次有效速度,取中位数或加权平均,再展示给用户。
后端配合要点:别让 lengthComputable 总是 false
前端能算出速度的前提,是服务端让 event.lengthComputable === true。这依赖服务端响应头里有 Content-Length,但更关键的是——它得在上传过程中就存在。
多数 Node.js 框架(如 Express + multer)默认等整个文件收完才返回响应,这时 onprogress 已经结束了。要让它生效,后端至少得做到:
- 收到每个 chunk 后立即返回一个空的
200 OK响应(哪怕只是res.end()),并带上Content-Length: 0 - 或者用流式响应,例如 Express 中
res.write('')并保持连接打开(需设置res.flushHeaders()) - Nginx 用户注意:确保配置了
proxy_buffering off;和chunked_transfer_encoding on;,否则代理层会攒满再吐,前端收不到中间进度
最稳妥的做法是:前端用 XMLHttpRequest,后端用简单 POST 接收裸二进制(不走 multipart),自己解析 req.on('data') 流,这样可控性最高。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











