js实现分包传输大文件
实现大文件分包传输的方法
在JavaScript中实现大文件分包传输的核心思路是将文件分割为多个小块(chunks),分别上传或传输,最后在服务端合并。以下为具体实现方法:
前端文件分块处理
使用File对象的slice方法分割文件,结合Blob类型处理二进制数据:
function splitFile(file, chunkSize = 5 * 1024 * 1024) {
const chunks = [];
let offset = 0;
while (offset < file.size) {
const chunk = file.slice(offset, offset + chunkSize);
chunks.push(chunk);
offset += chunkSize;
}
return chunks;
}
分块上传逻辑
通过FormData或fetch API逐块上传,建议添加重试机制:
async function uploadChunks(chunks, uploadUrl) {
const uploadResults = [];
for (let i = 0; i < chunks.length; i++) {
const formData = new FormData();
formData.append('chunk', chunks[i]);
formData.append('chunkIndex', i);
formData.append('totalChunks', chunks.length);
const response = await fetch(uploadUrl, {
method: 'POST',
body: formData
});
uploadResults.push(await response.json());
}
return uploadResults;
}
服务端合并处理
服务端需要实现两个接口:
- 接收分块并临时存储
- 合并所有分块为完整文件
Node.js示例(使用Express):
const fs = require('fs');
const path = require('path');
// 接收分块
app.post('/upload-chunk', (req, res) => {
const { chunk, chunkIndex, totalChunks } = req.body;
const tempDir = path.join(__dirname, 'temp');
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir);
}
const chunkPath = path.join(tempDir, `chunk-${chunkIndex}`);
fs.writeFileSync(chunkPath, chunk);
res.json({ success: true, chunkIndex });
});
// 合并分块
app.post('/merge-chunks', (req, res) => {
const { fileName, totalChunks } = req.body;
const tempDir = path.join(__dirname, 'temp');
const writeStream = fs.createWriteStream(fileName);
for (let i = 0; i < totalChunks; i++) {
const chunkPath = path.join(tempDir, `chunk-${i}`);
const chunkData = fs.readFileSync(chunkPath);
writeStream.write(chunkData);
fs.unlinkSync(chunkPath);
}
writeStream.end();
res.json({ success: true });
});
优化建议
- 断点续传:记录已上传的分块索引,支持中断后继续上传
- 并行上传:使用
Promise.all实现多个分块同时上传 - 进度监控:通过
XMLHttpRequest的progress事件或fetch的ReadableStream跟踪进度 - 文件校验:在合并后计算文件的MD5或SHA哈希值进行完整性验证
完整工作流程
- 前端计算文件哈希作为唯一标识
- 查询服务端是否已存在相同文件
- 若需上传,先获取已上传的分块列表
- 只上传缺失的分块数据
- 所有分块上传完成后触发合并请求
这种方式适合大文件传输,能有效降低网络中断风险,提高传输稳定性。







