const CHUNK_SIZE = 1024 * 1024 // 每个切片的大小
let file // 选择的文件对象
let currentChunk = 0 // 当前上传的切片序号
let totalChunks = 0 // 总切片数
let uploadUrl = 'http://localhost:3000' // 上传接口的 URL
// 选择文件时触发
document
.getElementById('file-input')
.addEventListener('change', function (event) {
file = event.target.files[0]
totalChunks = Math.ceil(file.size / CHUNK_SIZE)
})
// 点击上传按钮时触发
document.getElementById('upload-button').addEventListener('click', function () {
if (!file) {
alert('请先选择文件')
return
}
uploadChunk()
})
//
// 上传切片
function uploadChunk() {
let start = currentChunk * CHUNK_SIZE
let end = Math.min(start + CHUNK_SIZE, file.size)
let chunk = file.slice(start, end) // 从文件中获取当前切片的数据
let formData = new FormData()
formData.append('file', chunk, file.name)
formData.append('chunk', currentChunk)
formData.append('totalChunks', totalChunks)
fetch(uploadUrl, {
method: 'POST',
body: formData,
})
.then(function (response) {
if (response.ok) {
// 切片上传成功,继续上传下一个切片
currentChunk++
if (currentChunk < totalChunks) {
uploadChunk()
} else {
// 所有切片上传完成
console.log('文件上传完成')
}
} else {
// 切片上传失败,重试该切片
console.error('切片上传失败')
uploadChunk()
}
})
.catch(function (error) {
// 切片上传失败,重试该切片
console.error('切片上传失败')
console.error(error)
uploadChunk()
})
}
const express = require('express')
const multer = require('multer')
const path = require('path')
const fs = require('fs')
const app = express()
const PORT = 3000
app.use(express.static('/index', path.join(__dirname, './文件上传.html')))
const uploadDir = path.join(__dirname, 'uploads')
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir)
}
const storage = multer.diskStorage({
destination: uploadDir,
filename: function (req, file, callback) {
let ext = path.extname(file.originalname)
let name = path.basename(file.originalname, ext)
let chunk = req.body.chunk
callback(null, `${name}-${chunk}${ext}`)
},
})
const upload = multer({
storage: storage,
})
app.post('/upload', upload.single('file'), function (req, res) {
let chunk = parseInt(req.body.chunk)
let totalChunks = parseInt(req.body.totalChunks)
if (chunk === totalChunks - 1) {
// 所有切片上传完成,将所有切片合并成一个文件
let ext = path.extname(req.file.originalname)
let name = path.basename(req.file.originalname, ext)
let filePath = path.join(uploadDir, `${name}${ext}`)
let writeStream = fs.createWriteStream(filePath)
for (let i = 0; i < totalChunks; i++) {
let chunkFilePath = path.join(uploadDir, `${name}-${i}${ext}`)
let readStream = fs.createReadStream(chunkFilePath)
readStream.pipe(writeStream)
}
writeStream.on('close', function () {
// 删除所有切片文件
for (let i = 0; i < totalChunks; i++) {
let chunkFilePath = path.join(uploadDir, `${name}-${i}${ext}`)
fs.unlinkSync(chunkFilePath)
}
res.sendStatus(200)
})
} else {
res.sendStatus(200)
}
})
app.listen(PORT, function () {
console.log(`文件切片上传示例运行在 http://localhost:${PORT}`)
})