JavaScript监控文件上传和下载进度:XHR与Axios实现详解
在文件上传和下载业务中,实时展示进度条是提升用户体验的关键。本文将解析如何利用原生 XMLHttpRequest API 的事件监听机制,以及 Axios 的请求配置项来实现精准的进度监控。内容涵盖准备条件、具体代码实现及常见问题排查。
结果或目标
在网络不稳定或网速变化的场景下,用户需要感知文件传输的状态。通过实现进度监控,可以获得从开始到结束的完整状态反馈,包括加载百分比、传输完成、失败或取消等信息。
准备条件
要实现准确的进度计算,服务器必须在 HTTP 响应头中提供 Content-Length 字段。如果总字节数未知(例如分块传输未指定长度),客户端将无法计算准确的进度百分比,此时 event.total 将为零或 lengthComputable 为 false。
使用 XMLHttpRequest 监控进度
XMLHttpRequest (XHR) 提供了丰富的进度相关事件,无需依赖第三方库即可实现监控。核心逻辑是在请求生命周期的不同阶段绑定事件监听器。
第1步:理解 XHR 进度事件
XHR 对象在处理数据时会触发以下关键事件:
loadstart:请求开始时触发 1 次。progress:接收更多数据时周期性触发,用于计算进度。error:遭遇错误时触发。abort:请求被主动停止时触发。load:请求成功完成时触发。loadend:请求结束时触发(无论成功或失败)。
第2步:监控下载进度
下载进度监听直接在 XMLHttpRequest 实例上添加事件。注意,必须在调用 open() 之前绑定事件,否则可能漏掉初始事件。
let xhr = new XMLHttpRequest();
// 必须在 open() 之前添加监听
xhr.addEventListener("progress", updateProgress);
xhr.addEventListener("load", transferComplete);
xhr.addEventListener("error", transferFailed);
xhr.addEventListener("abort", transferCanceled);
xhr.open('GET', '/file.zip');
xhr.send();
function updateProgress(event) {
if (event.lengthComputable) {
// 计算百分比:已加载 / 总量 * 100
let percent = (event.loaded / event.total) * 100;
console.log('下载进度:' + percent.toFixed(2) + '%');
}
}
function transferComplete() {
console.log("下载完成");
}
function transferFailed() {
console.log("下载失败");
}
function transferCanceled() {
console.log("下载已取消");
}
第3步:监控上传进度
上传进度的监听需要挂载在 xhr.upload 对象上,因为这是数据传输的方向区分点。
let xhr = new XMLHttpRequest();
// 监听 upload 对象的进度事件
xhr.upload.addEventListener("progress", updateProgress);
xhr.upload.addEventListener("load", transferComplete);
xhr.upload.addEventListener("error", transferFailed);
xhr.open('POST', '/upload');
xhr.send(formData);
function updateProgress(event) {
if (event.lengthComputable) {
let percent = (event.loaded / event.total) * 100;
console.log('上传进度:' + percent.toFixed(2) + '%');
}
}
使用 Axios 监控进度
Axios 基于 Promise,内置了处理进度的便捷配置项:onUploadProgress 和 onDownloadProgress。
第4步:配置 Axios 进度回调
在发起请求的配置对象中传入进度函数,Axios 会自动传递包含 loaded 和 total 属性的 progressEvent 对象。
axios({
method: 'post',
url: '/upload',
data: formData,
// 上传进度回调
onUploadProgress: (progressEvent) => {
let percent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
console.log('上传进度:' + percent + '%');
},
// 下载进度回调
onDownloadProgress: (progressEvent) => {
let percent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
console.log('下载进度:' + percent + '%');
}
});
第5步:结合 UI 组件实现(以 Vue + Element UI 为例)
在实际项目中,常需将进度同步至 UI 组件。以下是自定义上传逻辑配合 Axios 进度的示例:
customUpload(file) {
let formData = new FormData();
formData.append('file', file.file);
axios({
method: 'post',
url: this.$api.uploadFile,
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: (progressEvent) => {
// 计算整数百分比
let num = Math.floor((progressEvent.loaded / progressEvent.total) * 100);
// 更新视图层进度文本
this.loadingText = `进度:${num}%`;
// 通知 el-upload 组件更新进度条状态
file.onProgress({ percent: num });
}
}).then(res => {
if (res.code === 0) {
file.onSuccess(res);
}
}).finally(() => {
this.loading = false;
});
}
完成判断与排错
完成判断:当 load 事件触发且无错误时,表示传输成功完成。loadend 事件则在所有情况(包括错误和取消)结束后触发,可用于重置全局加载状态。
常见排错:
- 进度不更新:检查服务器是否返回了
Content-Length响应头。若缺失,event.total为 0,导致无法计算百分比。 - XHR 事件未触发:确保在
request.open()之前已经绑定了addEventListener。 - 上传进度不准:对于大型文件或分块传输,若后端未正确设置长度头,前端只能显示“加载中”而无法显示精确百分比。
简要总结
通过监听 XHR 的 progress 事件或使用 Axios 的进度回调配置,可以完美实现文件上传下载的实时监控。关键在于服务端配合提供正确的文件大小信息,并注意事件绑定的时机。以上就是 JavaScript 实现监控上传和下载进度的详细内容,更多关于 JS 网络请求优化、Axios 用法相关的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









