要用 XMLHttpRequest Level 2 的 upload.onprogress 精确计算文件上传百分比,核心是监听 xhr.upload.onprogress 事件,用 e.loaded / file.size 计算并取整,配合手动设置 0% 和 100% 边界值,确保在 open() 后、send() 前绑定事件。

要用 XMLHttpRequest Level 2(XHR2) 的 upload.onprogress 精确计算文件上传百分比,核心是监听 XMLHttpRequest.upload 对象的 progress 事件,并利用事件对象中的 loaded 和 total 属性做实时计算。
确保使用 XHR2 并启用 upload 监听
XHR2 要求浏览器支持(现代浏览器均支持),且必须在调用 open() 之后、send() 之前绑定 upload.onprogress。注意:upload 属性只对上传有效,不能监听下载进度(下载需用 onprogress 在 xhr 实例上)。
- 创建
new XMLHttpRequest() - 调用
xhr.open('POST', url),方法和 URL 必须先确定 - 立即绑定
xhr.upload.onprogress = handler,不能晚于send() - 再调用
xhr.send(formData)或xhr.send(blob)
onprogress 回调中正确计算百分比
onprogress 事件对象(event)提供两个关键属性:loaded 表示已上传字节数,total 表示总字节数(仅当服务端响应头含 Content-Length 或浏览器能预知大小时才可靠)。对文件上传,total 通常等于文件的 file.size,因此推荐以客户端已知的 file.size 为准,避免依赖 event.total(某些环境可能为 0)。
- 在
onprogress中:const percent = Math.round((e.loaded / file.size) * 100) - 注意
e.loaded可能略大于file.size(如触发多次或网络叠加),建议用Math.min(percent, 100)保险 - 不要四舍五入到小数点后多位——用户感知不到 0.01%,整数更稳定
处理边界情况:上传开始前、完成、失败
onprogress 不会触发上传开始(0%)和完成(100%)的精确时刻,需手动补全:
立即学习“Java免费学习笔记(深入)”;
- 在
send()前手动设进度为 0% - 监听
xhr.onload或xhr.onreadystatechange(当readyState === 4),此时设为 100% - 监听
xhr.onerror或xhr.onabort,清理或提示中断 - 避免重复触发 100%:可在
onload中检查是否已到 100%,或加标志位防重置
一个简洁可用的封装示例
以下代码不依赖框架,可直接运行:
function uploadFile(file, url) {
const xhr = new XMLHttpRequest();
const progressBar = document.getElementById('progress');
<p>// 开始前设为 0%
progressBar.value = 0;</p><p>xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
const percent = Math.min(Math.round((e.loaded / file.size) * 100), 100);
progressBar.value = percent;
}
};</p><p>xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
progressBar.value = 100;
console.log('上传成功');
}
};</p><p>xhr.onerror = function() {
console.error('上传失败');
};</p><p>const formData = new FormData();
formData.append('file', file);</p><p>xhr.open('POST', url);
xhr.send(formData);
}


















