返回
实现 Node.js 大文件断点续传:分块上传、文件合并和容错机制
前端
2023-10-02 12:10:09
引言
文件上传是大规模应用程序中一个常见的需求。然而,当处理大文件时,断点续传机制就显得至关重要,它允许用户在网络中断或其他错误发生后继续上传。
分块上传和合并
为了有效地处理大文件,我们采用分块上传的方法。将文件分成较小的块,并分别上传这些块。服务器接收块并将其存储在临时位置。一旦所有块都上传完毕,服务器将它们合并为一个完整的文件。
容错机制
为了提高可靠性,我们实施了容错机制。如果上传过程中发生错误,服务器将尝试重新上传失败的块。我们还使用 ETags 和 Last-Modified 头来确保只有尚未上传的块才会被重新上传。
技术选型
- Node.js: 服务器端框架
- Express: Node.js 框架
- Multer: 处理文件上传
- Axios: 处理 HTTP 请求
前端实现
前端代码负责将文件分块并通过 Axios 将其发送到服务器。
const chunkSize = 1024 * 1024; // 1MB
function chunkFile(file) {
const chunks = [];
let start = 0;
while (start < file.size) {
const end = Math.min(start + chunkSize, file.size);
chunks.push(file.slice(start, end));
start += chunkSize;
}
return chunks;
}
function uploadChunk(chunk, index, file) {
// 使用 Axios 发送块到服务器
}
后端实现
后端代码负责接收块、存储它们并合并文件。
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const app = express();
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('file'), async (req, res) => {
const file = req.file;
// 获取文件块索引
const index = parseInt(req.query.index);
// 将块保存到临时位置
const tempFilePath = `uploads/${file.filename}_${index}`;
fs.writeFileSync(tempFilePath, req.body);
// 如果这是最后一个块,则合并文件
if (index === file.chunks - 1) {
// 合并块
const chunks = [];
for (let i = 0; i < file.chunks; i++) {
const chunkPath = `uploads/${file.filename}_${i}`;
chunks.push(fs.readFileSync(chunkPath));
}
const mergedFile = Buffer.concat(chunks);
// 删除临时块
fs.unlinkSync(`uploads/${file.filename}_${index}`);
// 保存合并文件
fs.writeFileSync(`uploads/${file.originalname}`, mergedFile);
// 发送成功响应
res.json({ success: true });
} else {
// 发送继续上传响应
res.json({ success: true, continue: true });
}
});
示例代码
完整的示例代码可以在 GitHub 上找到。
结论
通过分块上传、文件合并和容错机制,我们创建了一个健壮且高效的大文件断点续传解决方案。这种解决方案消除了大文件上传的挑战,提高了应用程序的可靠性。