React 实战大文件分片上传:断点续传、并发切片与进度管控
test12026-10-161 次阅读
为什么需要分片上传
单文件直接 PUT 上传有几个现实问题:大文件占用一条连接太久、中途断网要从头再来、进度条只能粗粒度。把文件切成固定大小的片,逐片并发上传,就能并发利用带宽、断点续传只补缺失的片、进度按片累计。下面是一套可直接落地的实现。
切片与并发控制
先把文件按 5MB 切片,用一个带并发上限的上传池,避免一次性发起几百个请求把浏览器连接打满。
async function uploadFile(file: File, onProgress: (p: number) => void) {
const CHUNK = 5 * 1024 * 1024;
const total = Math.ceil(file.size / CHUNK);
const uploaded = new Set<number>(); // 已成功的片,用于续传
// 并发池:最多同时传 3 片
const limit = 3;
let cursor = 0;
let done = 0;
async function worker() {
while (cursor < total) {
const index = cursor++;
const start = index * CHUNK;
const blob = file.slice(start, start + CHUNK);
const fd = new FormData();
fd.append("index", String(index));
fd.append("file", blob);
fd.append("name", file.name);
await fetch("/api/upload/chunk", { method: "POST", body: fd });
uploaded.add(index);
done++;
onProgress(Math.round((done / total) * 100));
}
}
await Promise.all(Array.from({ length: limit }, () => worker()));
}
断点续传
续传的关键是服务端能告诉前端"哪些片已经收过"。前端先问一次已上传的片索引,跳过它们即可。
async function resumeUpload(file: File) {
const res = await fetch(`/api/upload/status?name=${encodeURIComponent(file.name)}`);
const { uploaded }: { uploaded: number[] } = await res.json();
const done = new Set(uploaded);
let cursor = 0;
while (done.has(cursor)) cursor++;
// 其余逻辑与上面一致,但 worker 起点为 cursor
}
React 组件里怎么用
把上传逻辑收进一个组件,进度用 state 驱动进度条。注意用一个 ref 保存控制器,方便在用户点取消时中止。
function ChunkUploader() {
const [progress, setProgress] = useState(0);
const [busy, setBusy] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
async function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0];
if (!file) return;
setBusy(true);
await uploadFile(file, setProgress);
setBusy(false);
}
return (
<div>
<input ref={inputRef} type="file" onChange={handleChange} disabled={busy} />
<progress value={progress} max={100} />
<span>{progress}%</span>
</div>
);
}
工程注意点
- 每片建议带 index 与文件唯一标识,服务端按 (name, index) 落盘,合并前校验片数。
- 合并放到最后一片成功后触发,或者由前端显式调用 /api/upload/merge。
- 并发数别太高,浏览器对同一域名的 HTTP/1.1 连接数有限,3 到 5 比较稳妥。
- 给上传加整体超时与重试,单片失败重传该片即可,不要整文件重来。
T
test1
文章作者
为什么需要分片上传 单文件直接 PUT 上传有几个现实问题:大文件占用一条连接太久、中途断网要从头再来、进度条只能粗粒...
- 分类
- 技术
- 发布时间
- 2026-10-16
- 字数
- 约 2284 字
- 阅读
- 1 次
