js实现分段上传
实现分段上传的基本思路
分段上传(Chunked Upload)通常用于大文件上传,将文件分割为多个小块依次上传,最后在服务器合并。这种方式能提高上传稳定性、支持断点续传,并减轻服务器压力。
前端代码实现
使用JavaScript的File对象和Blob.prototype.slice方法切割文件,通过FormData发送分片:

function uploadFile(file, chunkSize = 1024 * 1024) {
const totalChunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
const uploadNextChunk = () => {
const start = currentChunk * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('chunkIndex', currentChunk);
formData.append('totalChunks', totalChunks);
formData.append('fileName', file.name);
fetch('/upload', {
method: 'POST',
body: formData
}).then(response => {
if (currentChunk < totalChunks - 1) {
currentChunk++;
uploadNextChunk();
} else {
console.log('Upload complete');
}
});
};
uploadNextChunk();
}
// 使用示例
document.getElementById('fileInput').addEventListener('change', (e) => {
uploadFile(e.target.files[0]);
});
服务器端处理逻辑
以Node.js为例的简单合并逻辑:

const fs = require('fs');
const path = require('path');
const express = require('express');
const multer = require('multer');
const app = express();
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('chunk'), (req, res) => {
const { chunkIndex, totalChunks, fileName } = req.body;
const tempPath = path.join(__dirname, 'temp', fileName);
// 将分片追加到临时文件
fs.appendFileSync(tempPath, fs.readFileSync(req.file.path));
fs.unlinkSync(req.file.path);
if (parseInt(chunkIndex) === parseInt(totalChunks) - 1) {
// 全部分片上传完成,进行最终处理
const finalPath = path.join(__dirname, 'uploads', fileName);
fs.renameSync(tempPath, finalPath);
res.json({ success: true });
} else {
res.json({ success: true });
}
});
断点续传实现
需要记录已上传的分片信息:
// 前端记录已上传的分片
let uploadedChunks = new Set();
function resumeUpload(file, chunkSize) {
// 从服务器获取已上传分片信息
fetch('/getUploadedChunks?fileName=' + file.name)
.then(res => res.json())
.then(data => {
uploadedChunks = new Set(data.uploadedChunks);
startUpload(file, chunkSize);
});
}
function startUpload(file, chunkSize) {
// 跳过已上传的分片
for (let i = 0; i < totalChunks; i++) {
if (!uploadedChunks.has(i)) {
uploadChunk(i);
break;
}
}
}
进度显示实现
通过计算已上传分片比例显示进度:
function updateProgress(currentChunk, totalChunks) {
const progress = Math.round((currentChunk + 1) / totalChunks * 100);
document.getElementById('progress').textContent = `${progress}%`;
}
// 在每次分片上传成功后调用
updateProgress(currentChunk, totalChunks);
注意事项
- 分片大小建议设置为1MB-5MB,过小会增加请求次数,过大可能失去分片意义
- 服务器需要处理并发上传可能导致的文件顺序问题
- 考虑添加文件MD5校验确保完整性
- 临时文件需要定期清理机制






