实现原理
- 前端通过webuploader 把文件切成多个小文件
- 批量上传的调用后台接口
- 当前端发现文件都全部上传完后,通知服务器合并文件,调用merge合并
- 合并后保存到服务器
上传后的效果
实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload img</title>
<link rel="stylesheet" href="/assert/css/webuploader.css" />
<script src="/assert/js/jquery.js"></script>
<script src="/assert/js/webuploader.html5only.js"></script>
</head>
<body>
<a href="javascript:;" id="upload">上传</a>
<script>
var guid = WebUploader.guid();
var chunks = null;
var ext = null;
var uploader = WebUploader.create({
auto: true,
server: '/upload',
pick: '#upload',
chunked: true,
chunkSize: 1024 * 10,
chunkRetry: 3,
thread: 5,
formData: {
guid,
}
});
uploader.on( 'uploadAccept', function( file, response ) {
console.log('uploadAccept',response.flag)
if (!response.flag ) {
return false;
}else{
chunks = response.chunks;
ext = response.ext;
console.log('uploadAccept',response.ext)
return true
}
});
uploader.on('uploadError', function (file, reason) {
console.log(reason, 'error')
});
uploader.on('uploadSuccess', function (file, reason) {
console.log('file...',file)
$.ajax({
type: 'POST',
url: '/merge',
data: {
guid,
chunks,
ext
},
success (data) {
const {flag} = data;
console.log(flag)
}
})
});
uploader.on('error', function (type) {
console.log('error',type);
});
uploader.on('uploadComplete', function (file) {
console.log(file)
})
</script>
</body>
</html>
const fs = require('fs');
const path = require('path');
const md5 = require('md5');
const express = require('express');
const fileUpload = require('express-fileupload');
const bodyParser = require('body-parser');
const multipart = require('connect-multiparty');
const app = express();
// 生成上传
const uploadFileP = path.resolve(__dirname, `./upload`);
fs.existsSync(uploadFileP) || fs.mkdirSync(uploadFileP);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(fileUpload());
app.use('/assert', express.static(path.resolve(__dirname, `./assert`)));
app.post('/upload', (req, res) => {
console.log('/upload...')
if (!req.files) {
return res.status(500).send('no files were uploaded');
}
let file = req.files.file;
let body = req.body;
let {chunk, chunks} = body;
// 生成文件
let filePath = path.resolve(__dirname, `./upload/${req.body.guid}`);
if(!fs.existsSync(filePath)) fs.mkdirSync(filePath);
file.mv(path.resolve(filePath, `./${chunk}.part`), function(err) {
let done = true;
if (err)
return res.status(500).send(err);
for (let i = 0 ; i < chunks; i++) {
if(!fs.existsSync(path.resolve(filePath, `./${i}.part`))) {
done = false;
break;
}
}
if (done === true) {
res.json({flag: true, chunked: true, hasError: false, ext: path.extname(file.name), chunks});
} else {
res.json({
flag: true, chunked: false, hasError: false
})
}
});
});
//合并文件
app.post('/merge', function (req, res) {
const body = req.body;
const {guid, chunks, ext} = body;
let md = md5(`${guid}${new Date().toString()}${chunks}`);
let basePath = path.resolve(__dirname, `./upload/${guid}`);
let filePh = path.resolve(__dirname, `./upload/${md}${ext}`)
for (let i = 0; i< chunks; i++) {
try {
fs.appendFileSync(filePh, fs.readFileSync(path.resolve(basePath, `./${i}.part`)));
} catch (e) {
return req.json({flag: 0})
}
}
return res.json({flag: 1})
})
app.listen(3000, () => {
console.log('sever start..')
});
测试代码
http://127.0.0.1:3000/assert/index.html