使用XMLHttpRequest监听上传进度的方法
前端开发中,我们经常需要监控文件或数据上传的进度,给用户提供实时反馈。很多开发者熟悉fetch API发起网络请求,但fetch本身并不直接支持上传进度的监听,而XMLHttpRequest原生提供了progress事件用于追踪上传进度,因此可以通过XMLHttpRequest实现上传进度监听的需求。
XMLHttpRequest上传进度监听的核心原理
XMLHttpRequest对象包含一个upload属性,该属性是一个XMLHttpRequestUpload对象,专门用于处理上传相关的事件。我们可以给upload对象绑定progress事件,在事件回调中获取上传的进度信息。
progress事件对象包含两个关键属性:
loaded:已经上传的字节数
total:需要上传的总字节数(如果服务器未返回Content-Length,该值可能为0)
通过计算loaded / total * 100就能得到当前的上传百分比进度。
完整实现示例
以下是一个使用XMLHttpRequest监听文件上传进度的完整示例,包含前端上传逻辑和简单的进度展示:
// 获取页面元素
const fileInput = document.getElementById('fileInput');
const uploadBtn = document.getElementById('uploadBtn');
const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
uploadBtn.addEventListener('click', () => {
const file = fileInput.files[0];
if (!file) {
alert('请先选择要上传的文件');
return;
}
// 创建XMLHttpRequest实例
const xhr = new XMLHttpRequest();
// 假设的上传接口地址,实际使用时替换为真实接口
const uploadUrl = 'https://www.ipipp.com/api/upload';
// 配置请求方法和地址
xhr.open('POST', uploadUrl, true);
// 监听上传进度
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
// 计算上传百分比
const percentComplete = Math.round((event.loaded / event.total) * 100);
// 更新进度条和文本
progressBar.value = percentComplete;
progressText.textContent = `上传进度:${percentComplete}%`;
} else {
progressText.textContent = '无法计算上传进度';
}
});
// 监听请求完成事件
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
progressText.textContent = '上传完成';
console.log('上传成功,响应结果:', xhr.responseText);
} else {
progressText.textContent = '上传失败';
console.error('上传失败,状态码:', xhr.status);
}
});
// 监听请求错误事件
xhr.addEventListener('error', () => {
progressText.textContent = '上传发生错误';
console.error('网络错误,上传失败');
});
// 构建表单数据
const formData = new FormData();
formData.append('file', file);
formData.append('fileName', file.name);
// 发送请求
xhr.send(formData);
});对应的HTML结构示例如下:
<div class="upload-container"> <input type="file" id="fileInput" /> <button id="uploadBtn">开始上传</button> <div class="progress-info"> <progress id="progressBar" value="0" max="100"></progress> <span id="progressText">未开始上传</span> </div> </div>
注意事项
XMLHttpRequest的
progress事件只有在服务器返回的响应头中包含Content-Length时,才能正确计算total值,否则event.lengthComputable为false,无法获取准确的进度。如果需要取消上传,可以调用
xhr.abort()方法终止当前请求。如果后端接口需要携带认证信息(如Cookie、Token),可以通过
xhr.withCredentials = true开启跨域凭证携带,或者在请求头中手动添加Token字段。XMLHttpRequest是较早期的API,虽然兼容性更好,但如果项目环境支持,也可以结合其他方案实现进度监听,不过原生XMLHttpRequest的上传进度监听是目前最稳定的实现方式之一。
fetch与XMLHttpRequest的选择
fetch API基于Promise,语法更简洁,支持异步流程控制,但确实缺少上传进度监听的能力。如果项目只需要发起普通请求,不需要监听上传进度,优先选择fetch;如果需要监控上传进度,使用XMLHttpRequest是更合适的选择。目前没有原生的方式让fetch直接支持上传进度监听,因此不要尝试用fetch去实现该功能,避免走弯路。