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