前端文件上传进阶:分片、断点续传与体验优化
为什么需要优化文件上传
原生 <input type="file"> 在处理大文件时往往力不从心。想象一下,上传一个 100MB 的文件,浏览器直接卡死,没有任何进度提示——这不仅是性能问题,更是对用户体验的打击。
常见误区
很多项目直接使用 fetch 或 XMLHttpRequest 提交整个文件对象,这种方式存在明显缺陷:
<!-- 原生文件上传示例 -->
<input type="file" onchange="uploadFile(this.files[0])" />
<script>
function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
// 直接上传,没有进度,没有断点续传
fetch('/api/upload', {
method: 'POST',
body: formData
});
}
</script>
这种写法在中小文件中尚可接受,但一旦涉及大文件,网络波动或超时都可能导致前功尽弃,且用户无法感知当前状态。
核心解决方案
1. 分片上传
利用 File.slice() API 将大文件切割成小块,并行或串行发送。这不仅降低了单次请求的大小,也为进度条计算提供了基础。
class ChunkUploader {
constructor(file, options = {}) {
this.file = file;
this.chunkSize = options.chunkSize || 1024 * 1024; // 默认 1MB
. = .(file. / .);
. = ;
}
() {
promises = [];
( i = ; i < .; i++) {
start = i * .;
end = .(start + ., ..);
chunk = ..(start, end);
promises.(.(chunk, i));
}
.(promises);
.();
}
() {
formData = ();
formData.(, chunk);
formData.(, index);
formData.(, .);
formData.(, ..);
(, {
: ,
: formData
});
.++;
.(. / .);
}
() {
.();
}
() {
(, {
: ,
: { : },
: .({ : .., : . })
});
}
}
uploader = (file, { : * });
uploader.();


