webuploader 文件分片上传javascript
为了预研技术大文件分片上传, 找到百度团队维护的webuploader库做为基础。github L6zt
调研策略:css
不知道是文档写的差,仍是我理解差,或者本身没看全。总之是不太清晰的,可是比我司写的wiki要好多了👍html
接着就是一顿蒙搞,同时借鉴前人的东西... 后端本身用 node(epxress)写了简单的上传接口。前端 照着demo搞了搞结果就成功了。 只是demo里面有其余问题。
// node 服务器 只是为了作测试前端
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) => { 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) { // chunked 这个参数 貌似很重要 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..') });
// 前端资源html5
<!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 * 100, chunkRetry: 3, thread: 5, formData: { guid, } }); // 貌似检查分片上传 是否是 对的 uploader.on( 'uploadAccept', function( file, response ) { // resopnse 后端返回数据 if (!response.flag ) { return false; }else{ chunks = response.chunks; ext = response.ext; return true } }); uploader.on('uploadError', function (file, reason) { console.log(reason, 'error') }); // 分片上传(all)成功后 调用合并接口 uploader.on('uploadSuccess', function (file, reason) { $.ajax({ type: 'POST', url: '/merge', data: { guid, chunks, ext }, success (data) { const {flag} = data; console.log(flag) } }) }); uploader.on('error', function (type) { console.log(type); }); uploader.on('uploadComplete', function (file) { console.log(file) }) </script> </body> </html>
// 效果图
项目地址java