Node.js 大文件上传(分片 + 断点续传)
大文件上传通过分片上传 + 断点续传提高稳定性和速度。
核心概念
- 分片上传:将大文件切分成小块(如 4MB),并行上传,失败只重传该片
- 断点续传:记录已上传分片,中断后从断点继续,无需重新上传整个文件
前端实现
js
// 切片函数(每片 4MB)
const chunkFun = (file, size = 1024 * 1024 * 4) => {
const chunks = []
for (let i = 0; i < file.size; i += size) {
chunks.push(file.slice(i, i + size))
}
return chunks
}
// 并行上传 + 发起合并请求
const uploadFile = (chunks) => {
const list = chunks.map((chunk, i) => {
const fd = new FormData()
fd.append('index', i)
fd.append('total', chunks.length)
fd.append('fileName', 'video')
fd.append('file', chunk)
return fetch('http://127.0.0.1:3000/up', { method: 'POST', body: fd })
})
Promise.all(list).then(() => {
fetch('http://127.0.0.1:3000/merge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fileName: 'video' })
})
})
}注意:
file必须放在 FormData 最后一个,因为 multer 按顺序读取字段。
后端实现
bash
npm install express multer corsjs
import express from 'express'
import multer from 'multer'
import cors from 'cors'
import fs from 'node:fs'
import path from 'node:path'
// 存储配置:文件名为 index-文件名 格式
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => cb(null, `${req.body.index}-${req.body.fileName}`)
})
const upload = multer({ storage })
const app = express()
app.use(cors())
app.use(express.json())
// 接收分片
app.post('/up', upload.single('file'), (req, res) => res.send('ok'))
// 合并分片
app.post('/merge', async (req, res) => {
const uploadPath = './uploads'
let files = fs.readdirSync(path.join(process.cwd(), uploadPath))
// 按 index 排序(避免乱序)
files = files.sort((a, b) => a.split('-')[0] - b.split('-')[0])
const writePath = path.join(process.cwd(), 'video', `${req.body.fileName}.mp4`)
// 逐个追加合并
files.forEach((item) => {
fs.appendFileSync(writePath, fs.readFileSync(path.join(uploadPath, item)))
fs.unlinkSync(path.join(uploadPath, item)) // 合并后删除分片
})
res.send('合并完成')
})
app.listen(3000)合并逻辑
uploads/
0-video 1-video 2-video 3-video
↓ sort 排序(避免顺序错乱)
↓ forEach → appendFileSync 追加
↓ unlinkSync 删除已合并的分片
video/video.mp4 ← 完整文件