Nodejs文件上傳、監(jiān)聽上傳進(jìn)度的代碼
前言
文件上傳如果加上進(jìn)度條會有更好的用戶體驗(yàn)(尤其是中大型文件),本文使用 Nodejs
配合前端完成這個(gè)功能。
前端我們使用 FormData
來作為載體發(fā)送數(shù)據(jù)。
效果
前端部分
HTML 部分 和 Js 部分
<input type="file" id="file" /> <!-- 進(jìn)度條 --> <progress id="progress" value="0" max="100"></progress> // 獲取 input file 的 dom 對象 const inputFile = document.querySelector('#file'); // 監(jiān)聽 change 事件 inputFile.addEventListener('change', function() { // 使用 formData 裝載 file const formData = new FormData(); formData.append('file', this.files[0]); // 上傳文件 upload(formData); })
下面我們實(shí)現(xiàn) upload 方法。
使用 XMLHttpRequest 的方式
const upload = ( formData ) => { const xhr = new XMLHttpRequest(); // 監(jiān)聽文件上傳進(jìn)度 xhr.upload.addEventListener('progress', function(e) { if (e.lengthComputable) { // 獲取進(jìn)度 const progress = Math.round((e.loaded * 100) / e.total); document.querySelector('#progress').setAttribute('value', progress); } },false); // 監(jiān)聽上傳完成事件 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 如何監(jiān)聽文件上傳進(jìn)度呢:
const upload = ( formData ) => { $.ajax({ type: 'post', url: 'http://127.0.0.1:3000/upload', data: formData, // 不進(jìn)行數(shù)據(jù)處理和內(nèi)容處理 processData: false, contentType: false, // 監(jiān)聽 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 上傳并監(jiān)聽進(jìn)度
axios 使用量非常大,用它監(jiān)聽文件上傳更簡單,代碼如下:
const upload = async ( formData ) => { let config = { // 注意要把 contentType 設(shè)置為 multipart/form-data headers: { 'Content-Type': 'multipart/form-data' }, // 監(jiān)聽 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 部分
這部分比較簡單,其實(shí)就是單純的文件上傳,我們用 Koa 來實(shí)現(xiàn).
環(huán)境搭建及依賴包安裝
這里使用 koa2 ,安裝以下依賴包:
- koa
- @koa/router: koa 的路由
- @koa/cors:用于跨域
- koa-body: 解析 body 數(shù)據(jù)
- nodemon: 使用它啟動服務(wù),帶有熱更新
代碼部分
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 。
我們要監(jiān)聽文件流 end 事件,由于無法在事件回調(diào)里返回響應(yīng),因?yàn)闀?bào) 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; }) }); };
到這里就全部完成了。
這里注意一下:前端監(jiān)聽文件進(jìn)度不需要后端有什么特殊處理,后端僅僅是做了文件流的寫入而已。
總結(jié)
到此這篇關(guān)于Nodejs文件上傳、監(jiān)聽上傳進(jìn)度的文章就介紹到這了,更多相關(guān)Nodejs文件上傳、監(jiān)聽上傳進(jìn)度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JS實(shí)現(xiàn)批量上傳文件并顯示進(jìn)度功能
- JS插件plupload.js實(shí)現(xiàn)多圖上傳并顯示進(jìn)度條
- js實(shí)現(xiàn)帶進(jìn)度條提示的多視頻上傳功能
- JS實(shí)現(xiàn)上傳文件顯示進(jìn)度條
- JS+html5實(shí)現(xiàn)異步上傳圖片顯示上傳文件進(jìn)度條功能示例
- 基于JS實(shí)現(xiàn)視頻上傳顯示進(jìn)度條
- 原生javascript上傳圖片帶進(jìn)度條【實(shí)例分享】
- 教你3分鐘利用原生js實(shí)現(xiàn)有進(jìn)度監(jiān)聽的文件上傳預(yù)覽組件
- Node.js上傳文件功能之服務(wù)端如何獲取文件上傳進(jìn)度
- JavaScript實(shí)現(xiàn)監(jiān)控上傳和下載進(jìn)度
- JavaScript獲取上傳進(jìn)度的幾種方式實(shí)現(xiàn)
相關(guān)文章
在Node.js中實(shí)現(xiàn)后端與前端的交互的方法詳解
在前后端不分離的應(yīng)用模式中,前端頁面看到的效果都是由后端控制,由后端渲染頁面或重定向,也就是后端需要控制前端的展示,前端與后端的耦合度很高, 所以本文給大家介紹了在Node.js中實(shí)現(xiàn)后端與前端的交互的方法,需要的朋友可以參考下2024-09-09nodejs環(huán)境使用Typeorm連接查詢Oracle數(shù)據(jù)
這篇文章主要介紹了nodejs環(huán)境使用Typeorm連接查詢Oracle數(shù)據(jù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用詳解
node-schedule是 Node.js 的一個(gè)定時(shí)任務(wù)(crontab)模塊。這篇文章主要介紹了Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用,需要的朋友可以參考下2020-04-04Node.js實(shí)現(xiàn)鏈?zhǔn)交卣{(diào)
這篇文章介紹了Node.js實(shí)現(xiàn)鏈?zhǔn)交卣{(diào)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Node.js之如何創(chuàng)建TCP服務(wù)器端
這篇文章主要介紹了Node.js之如何創(chuàng)建TCP服務(wù)器端問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09