大文件分片上传是指将体积较大的文件在前端切割成多个小块,再逐块发送给服务器,最后由服务器合并还原。这种方式能避免请求超时,并支持断点续传,是文件上传功能中处理大文件的常用方案。

为什么需要分片上传
普通表单或 ajax 直接上传大文件时,容易遇到浏览器或服务器限制,例如请求体大小上限、网络波动导致整体失败。分片上传把风险分散到每个小块上,单个分片失败只需重传该分片。
- 降低单次请求体积,规避服务器限制
- 支持暂停与续传,提升用户体验
- 可并行上传多个分片,提高吞吐
前端如何切片
使用浏览器提供的 Blob.slice 方法即可将文件拆分为指定大小的块。下面以 JavaScript 为例展示基础切片逻辑。
// 将文件按固定大小切片
function createChunks(file, chunkSize) {
const chunks = [];
let cur = 0;
while (cur < file.size) {
// slice 返回新的 Blob 对象
chunks.push(file.slice(cur, cur + chunkSize));
cur += chunkSize;
}
return chunks;
}
const file = document.querySelector('input[type=file]').files[0];
const list = createChunks(file, 2 * 1024 * 1024); // 每片 2MB
console.log('分片数量:', list.length);
后端接收与合并
后端按分片索引暂存文件,全部到达后按顺序合并。以下 Node.js 示例演示接收与合并过程。
const fs = require('fs');
const path = require('path');
// 保存单个分片
function saveChunk(req, res) {
const { index, hash } = req.query;
const dir = path.join(__dirname, 'tmp', hash);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const filePath = path.join(dir, index);
const ws = fs.createWriteStream(filePath);
req.pipe(ws);
ws.on('finish', () => res.end('ok'));
}
// 合并所有分片
function mergeChunks(hash, count, output) {
const dir = path.join(__dirname, 'tmp', hash);
const ws = fs.createWriteStream(output);
for (let i = 0; i < count; i++) {
const data = fs.readFileSync(path.join(dir, String(i)));
ws.write(data);
}
ws.end();
fs.rmdirSync(dir, { recursive: true });
}
关键注意事项
| 事项 | 说明 |
|---|---|
| 分片大小 | 通常设为 1MB 到 5MB,兼顾请求数与内存占用 |
| 唯一标识 | 用文件 hash 区分不同文件,避免冲突 |
| 失败重试 | 记录已传分片,仅重传失败部分 |
通过上述方式,文件上传功能中的大文件分片上传处理就能稳妥落地。实际项目中还可加入进度条、并发控制与秒传优化。