使用fs模块的读流写流方式将文件合并
我遇到的问题:
1. 切片是正常上传的,但是同一个图片多次上传,有时候合并的文件是正确的,能够预览,有的时候无法解析
2. 猜测: 每一个切片的读流写流是异步操作,在merge(index) 和 merge(index+1)可能存在冲突,而且pipe后写流是默认关闭的,所以加了
rs.pipe(ws, {end: false}) // 需要合并多次,不关闭ws,
rs.on('end', () => { // 读完之后在合并下一个片段
merge(index + 1)
})
如何跑起来
1. 将index.html 和 server.js放在同一个文件夹,在cmd使用 `http-server` 挂在前端index.html
2. 使用cnpm下载koa, koa-body然后使用node(version=10+)运行server.js
const koa = require('koa')
const koaBody = require('koa-body')
const fs = require('fs')
const app = new koa()
// 使用koaBody托管上传文件,koaBody会自动把文件上传到upload文件夹里,并且以一个随机字符串命名
app.use(koaBody({
multipart: true,
formLimit: 15,
formidable: {
uploadDir: __dirname + '/upload'
}
})
)
app.use(async (ctx, next) => {
// 解决跨域
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
await next();
});
app.use(async (ctx, next) => {
if(ctx.path === '/upload') {
// 上传到后端的文件名重新命名下, 合并时才找得到
let fd = ctx.request.body
let filePath = ctx.request.files.file.path
let newFileName = `${fd.fileName}-${fd.index}-${fd.uuid}`
let newFilePath = filePath.substr(0, filePath.lastIndexOf('\\') + 1) + newFileName
fs.renameSync(filePath, newFilePath)
ctx.body='upload success'
}
else if(ctx.path === '/merge') {
let {uuid, count, fileName} = ctx.request.body
let ws, rs
function merge(index) {
if(index >= count) {
ws && ws.close()
// read流默认autoclose
return
}
rs = fs.createReadStream(__dirname + '/upload/' + `${fileName}-${index}-${uuid}`)
ws = fs.createWriteStream(__dirname + '/upload/' + `${uuid}-${fileName}`, { flags: 'a' }) // 以追加的方式插入数据
rs.pipe(ws, {end: false}) // 需要合并多次,不关闭ws,
rs.on('end', () => { // 读完之后在合并下一个片段
merge(index + 1)
})
}
merge(0)
ctx.body='merge success'
}
await next()
})
app.listen(8081, () => {
console.log('on')
})