使用js将文件分片:
/**
*
* @param {*} file file是文件
* @param {*} chunkSize chunkSize是每个块的大小,默认64k
* 方法的返回值是一个数组,数组里面的每个元素就是切好的块文件,可以直接上传
*/
function uploadFun(file, chunkSize=64 * 1024) {
return new Promise((resolve) => {
console.log(file);
// 视频名字
const fileName = new Date().getTime() + Math.floor(Math.random() * 150) + "_" + file.name
console.log(fileName);
console.log(chunkSize);
let fileList = []
let uploadSize = 0 // 当前上传了多少
while (uploadSize < file.size) {
const fileChunk = file.slice(uploadSize, uploadSize + chunkSize)
const formData = createFormData({
name: file.name,
type: file.type,
size: file.size,
fileName: fileName,
uploadSize: uploadSize,
file: fileChunk,
chunkSize
})
fileList.push(formData)
uploadSize += fileChunk.size
}
resolve(fileList)
})
}
// 创建分块文件
function createFormData({
name,
type,
size,
fileName,
uploadSize,
file,
chunkSize
}) {
const fd = new FormData()
fd.append('name', name)
fd.append('type', type)
fd.append('size', size)
fd.append('fileName', fileName)
fd.append('uploadSize', uploadSize)
fd.append('file', file)
fd.append('chunkSize', chunkSize)
return fd
}
在上述代码中,调用uploadFun方法会返回一个数组,数组的每一个元素就是对应的分片文件。
特别注意:使用uploadFun方法返回的数组去上传时,要使用同步调用,就是第一个分片文件上传完成之后,再上传下一个。
使用node+express将文件合并
以下时后端代码,在运行之前要安装包:
npm i express --save
npm i express-fileupload --save
const express = require('express');
const bodyParser = require('body-parser');
const uploader = require('express-fileupload');
const { resolve } = require('path');
const { existsSync, appendFileSync, writeFileSync } = require('fs');
const app = express()
const PORT = '4001'
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(bodyParser.json())
app.use(uploader())
app.use('/', express.static('upload_file'))
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Authorization,X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method')
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PATCH, PUT, DELETE')
res.header('Allow', 'GET, POST, PATCH, OPTIONS, PUT, DELETE')
next();
})
app.post('/upload/fragment', (req, res) => {
// console.log(req.body);
if (!req.files) {
res.send({
code: 500,
message: '请上传文件'
})
return
}
const filePath = resolve(__dirname, './upload_file/' + req.body.fileName)
// 第一次上传,直接创建文件
if (req.body.uploadSize == 0) {
console.log(req.files.file);
writeFileSync(filePath, req.files.file.data)
res.send({
code: 200,
message: '文件已创建'
})
return
}
// 后续上传,追加
if(!existsSync(filePath)) {
res.send({
code: 500,
message: '文件上传失败'
})
return
}
appendFileSync(filePath, req.files.file.data)
// 最后一次,返回地址
if (Number(req.body.uploadSize) + Number(req.body.chunkSize) >= Number(req.body.size)) {
res.send({
code: 200,
message: '文件上传成功',
data: {
url: `http://127.0.0.1:4001/${req.body.fileName}`
}
})
return
}
res.send({
code: 200,
message: '分段上传成功'
})
})
app.listen(PORT, () => {
console.log(`http://127.0.0.1:${PORT}`);
})