JavaScript如何实现文件上传_怎样处理大文件和进度显示

JavaScript文件上传核心用FormData+XMLHttpRequest或fetch;进度显示依赖xhr.upload.onprogress;大文件需分片上传+断点续传;辅以类型大小校验、按钮禁用、失败重试及本地预览等体验优化。

JavaScript 实现文件上传,核心是利用 XMLHttpRequest 或更现代的 fetch 配合 FormData;处理大文件和进度显示,则依赖 XMLHttpRequest.upload.onprogressfetch 目前不支持原生上传进度),并常需分片上传来提升稳定性与可控性。

基础文件上传:用 FormData + XMLHttpRequest

这是最通用、兼容性好的方式,适合中小文件(如几 MB 以内):

  • 创建 FormData 实例,把 files[0] 追加进去
  • 新建 XMLHttpRequest,设置请求方法(POST)、URL,并监听 loaderror
  • 调用 xhr.send(form) 即可发送

服务端收到的是标准 multipart 表单数据,无需额外解析库(如 Express 中可用 multer)。

显示上传进度:必须用 XMLHttpRequest.upload

fetch 暂不提供上传过程的进度事件,所以要实时显示进度条,得用 XMLHttpRequest 并监听其 upload.onprogress

  • xhr.upload.onprogress = e => { ... } 中获取 e.loaded(已传字节数)和 e.total(总字节数)
  • 计算百分比:Math.round((e.loaded / e.total) * 100),更新 UI 元素(如 或自定义 div)
  • 注意:当文件本地读取或网络限速时,e.total 可能为 0(如某些浏览器对 Blob 上传未设 total),建议加空值判断

上传大文件(100MB+):分片上传 + 断点续传

直接传大文件容易失败、无法暂停、占用内存高。推荐分片上传(chunked upload):

  • 前端用 File.prototype.slice() 将文件切分为固定大小块(如 5MB/片)
  • 每片单独发请求,携带标识(如文件唯一 hash、分片序号、总片数),后端按序合并或暂存
  • 上传前先向服务端查询已传哪些片(“秒传”和断点续传的基础),跳过已成功上传的片
  • 所有片上传完成后,发一个“合并”请求,服务端拼接并生成最终文件

可配合 Web Worker 处理切片和 hash 计算,避免阻塞主线程;使用 AbortController 支持手动取消。

增强体验的小技巧

让上传更健壮、用户更安心:

  • 上传前校验文件类型、大小(file.size > MAX_SIZE),提前提示而非等后端返回 413
  • 禁用上传按钮 + 显示 loading 状态,防止重复提交
  • 上传失败时保留进度,支持重试(尤其分片场景下只重传失败片)
  • 使用 URL.createObjectURL(file) 快速预览图片/视频,无需上传即可确认内容

不复杂但容易忽略。