Nodejs檔案上傳、監聽上傳進度的程式碼
阿新 • • 發佈:2020-03-31
前言
檔案上傳如果加上進度條會有更好的使用者體驗(尤其是中大型檔案),本文使用 Nodejs
配合前端完成這個功能。
前端我們使用 FormData
來作為載體傳送資料。
效果
前端部分
HTML 部分 和 Js 部分
<input type="file" id="file" /> <!-- 進度條 --> <progress id="progress" value="0" max="100"></progress> // 獲取 input file 的 dom 物件 const inputFile = document.querySelector('#file'); // 監聽 change 事件 inputFile.addEventListener('change',function() { // 使用 formData 裝載 file const formData = new FormData(); formData.append('file',this.files[0]); // 上傳檔案 upload(formData); })
下面我們實現 upload 方法。
使用 XMLHttpRequest 的方式
const upload = ( formData ) => { const xhr = new XMLHttpRequest(); // 監聽檔案上傳進度 xhr.upload.addEventListener('progress',function(e) { if (e.lengthComputable) { // 獲取進度 const progress = Math.round((e.loaded * 100) / e.total); document.querySelector('#progress').setAttribute('value',progress); } },false); // 監聽上傳完成事件 xhr.addEventListener('load',()=>{ console.log(':smile:上傳完成') },false); xhr.open('post','http://127.0.0.1:3000/upload'); xhr.send(formData); }
使用 jQuery 的 ajax 上傳
jQuery 目前的使用量依然龐大,那麼使用 jQuery 的 ajax 如何監聽檔案上傳進度呢:
const upload = ( formData ) => { $.ajax({ type: 'post',url: 'http://127.0.0.1:3000/upload',data: formData,// 不進行資料處理和內容處理 processData: false,contentType: false,// 監聽 xhr xhr: function() { const xhr = $.ajaxSettings.xhr(); if (xhr.upload) { xhr.upload.addEventListener('progress',e => { const { loaded,total } = e; var progress = (loaded / total) * 100; document.querySelector('#progress').setAttribute('value',progress); },false ); return xhr; } },success: function(response) { console.log('上傳成功'); } }); }
使用 axios 上傳並監聽進度
axios 使用量非常大,用它監聽檔案上傳更簡單,程式碼如下:
const upload = async ( formData ) => { let config = { // 注意要把 contentType 設定為 multipart/form-data headers: { 'Content-Type': 'multipart/form-data' },// 監聽 onUploadProgress 事件 onUploadProgress: e => { const {loaded,total} = e; // 使用本地 progress 事件 if (e.lengthComputable) { let progress = loaded / total * 100; document.querySelector('#progress').setAttribute('value',progress); } } }; const { status } = await axios.post('http://127.0.0.1:3000/upload',formData,config); if (res.status === 200) { console.log('上傳完成:grinning:'); } }
Nodejs 部分
這部分比較簡單,其實就是單純的檔案上傳,我們用 Koa 來實現.
環境搭建及依賴包安裝
這裡使用 koa2 ,安裝以下依賴包:
- koa
- @koa/router: koa 的路由
- @koa/cors:用於跨域
- koa-body: 解析 body 資料
- nodemon: 使用它啟動服務,帶有熱更新
程式碼部分
const Koa = require('koa'); const Router = require('@koa/router'); const koaBody = require('koa-body'); const path = require('path'); const fs = require('fs'); const cors = require('@koa/cors'); const app = new Koa(); const router = new Router(); router.all('/upload',async ctx => { // 處理檔案上傳 const res = await dealFile(ctx); res && (ctx.body = { status: 200,msg: 'complete' }); }); // 中介軟體部分 app.use(cors()); app.use( koaBody({ multipart: true,formidable: { maxFileSize: 2000 * 1024 * 1024 //最大2G } }) ); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
dealFile 方法處理上傳的檔案
出於效能考慮,操作 file 毫無疑問要使用 stream 。
我們要監聽檔案流 end 事件,由於無法在事件回撥裡返回響應,因為會報 404,所以需要使用 Promise
來封裝一下,然後用 async、await
const dealFile = ctx => { const { file } = ctx.request.files; const reader = fs.createReadStream(file.path); const writer = fs.createWriteStream( // 檔案上傳到 image 資料夾中 path.resolve(__dirname,'./image',file.name) ); return new Promise((resove,reject) => { reader.pipe(writer); reader.on('end',() => { resove(true); }); reader.on('error',err => { throw err; }) }); };
到這裡就全部完成了。
這裡注意一下:前端監聽檔案進度不需要後端有什麼特殊處理,後端僅僅是做了檔案流的寫入而已。
總結
到此這篇關於Nodejs檔案上傳、監聽上傳進度的文章就介紹到這了,更多相關Nodejs檔案上傳、監聽上傳進度內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!