javascript中监听文件上传进度需绑定onprogress到xhr.upload而非xhr本身,通过event.loaded和event.total计算百分比,并确保服务端设置access-control-expose-headers: content-length以支持跨域获取总大小。

JavaScript 中通过 XMLHttpRequest 的 onprogress 事件监听文件上传进度,核心在于使用 upload 属性绑定事件,并从事件对象中读取已上传字节数和总字节数。
确保使用 XMLHttpRequest 实例的 upload 属性
onprogress 事件必须绑定在 xhr.upload 对象上,而不是 xhr 本身——因为上传进度属于“上传过程”,而 xhr 上的 onprogress 监听的是下载进度(如请求响应体接收)。
- 正确写法:
xhr.upload.onprogress = handler - 错误写法:
xhr.onprogress = handler(这监听的是响应下载,对上传无效)
从 progress 事件中提取进度数据
事件回调函数接收一个 ProgressEvent 对象,它包含两个关键属性:
-
event.loaded:已上传的字节数(number) -
event.total:文件总字节数(number),仅当服务端返回了Content-Length或支持Content-Range且预检成功时才可靠;若为0,说明无法获知总大小(如流式上传、服务端未设置 CORS 头Access-Control-Expose-Headers: Content-Length)
因此计算百分比前建议先判断:if (event.total > 0) { percent = (event.loaded / event.total) * 100 }
注意 CORS 与响应头暴露
如果后端是跨域服务,浏览器默认不会将 Content-Length 等响应头暴露给前端 JavaScript。要让 event.total 可用,后端需在响应中显式声明:
Access-Control-Expose-Headers: Content-Length- (可选但推荐)
Access-Control-Allow-Origin: *或具体域名
否则即使服务端返回了 Content-Length,前端看到的 event.total 仍为 0,导致无法计算准确进度。
完整简易示例
以下是一个带进度更新的文件上传片段:
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', e => {
const file = e.target.files[0];
if (!file) return;
<p>const xhr = new XMLHttpRequest();</p><p>// ✅ 绑定到 upload 对象
xhr.upload.onprogress = e => {
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
console.log(<code>上传中:${percent.toFixed(1)}%</code>);
// 更新页面进度条:progressBar.style.width = <code>${percent}%</code>;
}
};</p><p>xhr.onload = () => {
if (xhr.status >= 200 && xhr.status </p><p>xhr.onerror = () => console.error('上传失败');</p><p>xhr.open('POST', '/upload');
xhr.send(file);
});</p>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











