必须用 xmlhttprequest 的 upload.onprogress 监听上传进度,而非 request.onprogress;需拦截表单提交、正确使用 formdata 附带文件及字段;进度更新应节流或用 requestanimationframe;完成判断应依据响应体 success 字段而非 http 状态码。

如何用 XMLHttpRequest 监听上传进度而不是表单默认提交
表单默认提交会整页跳转或刷新,根本看不到进度条。必须拦截提交行为,改用 XMLHttpRequest(或 fetch)手动发请求,并监听 upload.onprogress 事件。
常见错误是只监听 request.onprogress——那是下载进度,对上传无效;必须取 request.upload.onprogress。
- 给
<form></form>加onsubmit="return false"或用event.preventDefault() - 创建
XMLHttpRequest实例后,立刻绑定upload.onprogress,再调用send() - 注意:IE10+ 支持
upload.onprogress,IE9 及更早版本不支持,需降级提示
FormData 怎么正确附带文件和额外字段
直接把 <input type="file"> 的 files[0] 丢进 FormData 就行,但容易漏掉 name 属性——后端靠这个字段名接收文件,不是靠 input 的 id 或 class。
如果还要传其他参数(如用户 ID、目录路径),别拼在 URL 里,统一 append 到 FormData 中,否则 multipart 请求体结构会乱。
-
formData.append('avatar', fileInput.files[0])—— 第一个参数是后端 expect 的字段名 -
formData.append('user_id', '12345')—— 普通字段也走 append,不要用JSON.stringify - 避免
formData.append('files', fileInput.files)——files是 FileList,不是单个 File,会导致类型错误
进度条 DOM 更新卡顿?别在 onprogress 里直接操作样式
浏览器每秒可能触发几十次 onprogress,每次直接设 element.style.width = percent + '%' 会频繁重排,尤其在低端设备上明显卡顿。
真正轻量的做法是节流更新 + 使用 requestAnimationFrame 批量同步视觉变化。
- 用
let lastUpdate = 0记录上次更新时间,间隔 ≥ 16ms 再刷新 DOM - 或用
requestAnimationFrame替代直接赋值:rafId = requestAnimationFrame(() => bar.style.width = percent + '%') - 进度数值建议保留一位小数:
Math.round((e.loaded / e.total) * 100 * 10) / 10,避免 99.9999999% 这种浮点误差显示
上传完成后的状态处理:别只看 status === 200
HTTP 状态码 200 只代表请求发出去且服务器返回了响应,不代表业务成功。比如后端校验失败可能仍返回 200 并带 JSON 错误体,也可能返回 400 但没配 CORS 导致前端捕获不到。
真正可靠的判断依据是响应体内容 + 后端约定的 success 字段,而不是 status。
- 始终设置
request.responseType = 'json',方便解析 - 用
try/catch包裹JSON.parse(request.response),防止后端返回非 JSON 内容炸掉 - 检查
response.success === true或类似字段,再更新 UI;否则显示response.message - 上传中途取消(
request.abort())时,onload不会触发,要监听onabort单独处理
进度条逻辑本身简单,难的是边界情况:网络中断重试、大文件内存占用、重复提交防抖、服务端返回格式不一致——这些不写进代码里,上线后就会变成凌晨三点的告警。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











