做网页开发时,经常要处理文件上传。以前用户点一下“上传”,然后干等着,不知道传到哪一步了,心里没底。后来有了Ajax,可以异步上传,再加上进度条,体验就好多了。
为什么需要上传进度条
想象一下你传一个几百MB的视频去网站,点了上传按钮后页面卡住不动,你只能盯着屏幕猜:“到底在不在传?是不是卡了?” 这种体验很糟糕。加上进度条,用户能看到“已上传 65%”,心里就有数了,也不会反复点击按钮导致重复提交。
Ajax如何实现带进度的上传
关键在于 XMLHttpRequest 的 upload 属性。它提供了一个监听上传过程的接口,能实时拿到已上传字节数和总大小。
前端代码示例:
var xhr = new XMLHttpRequest();
var form = document.getElementById('uploadForm');
var fileInput = document.getElementById('file');
xhr.open('POST', '/upload', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var percent = (e.loaded / e.total) * 100;
document.getElementById('progress').style.width = percent + '%';
document.getElementById('percent').innerText = Math.round(percent) + '%';
}
};
xhr.onload = function() {
if (xhr.status === 200) {
console.log('上传完成');
}
};
var formData = new FormData();
formData.append('file', fileInput.files[0]);
xhr.send(formData);
HTML部分也很简单:
<input type="file" id="file">
<button type="button" onclick="uploadFile()">上传</button>
<div class="progress-bar">
<div id="progress" style="width: 0%; background: #4caf50; height: 20px; transition: width 0.3s;"></div>
</div>
<span id="percent">0%</span>
服务端不需要特殊处理
很多人以为进度条要服务端配合推送状态,其实不是。浏览器在上传数据时,会自动分段发送,XMLHttpRequest 能监听的是“正在发”的这个过程。只要后端能正常接收 multipart/form-data 格式的数据就行,比如 PHP 的 $_FILES 或 Node.js 的 multer 都可以直接用。
注意兼容性问题
IE10 以下不支持 onprogress 事件,如果还要兼容老版本,就得用 iframe 模拟或者上 Flash 方案,但现在大多数项目已经不用考虑这些了。主流浏览器都支持得很好。
小技巧:防止重复提交
上传开始后,可以把按钮置灰或禁用,避免用户手快连点。等 xhr.onload 或 xhr.onerror 触发后再恢复按钮可用状态。
加个进度条,看似小功能,但对用户体验提升很明显。特别是现在手机拍照动辄几十MB,网页上传不能还让用户盲等。