摘要:前言在開發中,文件上傳是一個非常常見非常重要的功能。本文將介紹如何用處理上傳的文件。前端界面如下用戶從瀏覽器中選擇文件,點擊上傳,將發起請求到服務器,服務器將接受到的文件存儲在服務器硬盤中。
前言
在Web開發中,文件上傳是一個非常常見、非常重要的功能。本文將介紹如何用Node處理上傳的文件。
需求分析由于現在前后端分離很流行,那么本文也直接采用前后端分離的做法。前端界面如下:
用戶從瀏覽器中選擇文件,點擊上傳,將發起http請求到服務器,服務器將接受到的文件存儲在服務器硬盤中。
前端部分ajax請求庫采用axios,為了簡化說明,前端限制上傳的文件類型只能為圖片,且一次只能上傳一張,有興趣的朋友可以自行補充,代碼如下:
后端部分Title
這是本文要介紹的重點,為了用高效流暢的方式來解析文件上傳請求,我們先引入formidable庫:
npm install formidable --save
formidable的流式解析器讓它成為了處理文件上傳的絕佳選擇,也就是說它能隨著數據塊的上傳接收它們,解析它們,并吐出特定的部分,相信熟悉流的朋友會很好理解。這種方式不僅快,還不會因為需要大量緩沖而導致內存膨脹,即便像視頻這種大型文件,也不會把進程壓垮。
首先,我們在根目錄下創建myImage文件,用于存放上傳的圖片(注意:如果沒有創建,會導致上傳報錯),接著,我們創建一個IncomingForm實例form,并且設置存放路徑為myImage文件夾。代碼如下:
var http = require("http") var formidable = require("formidable") var server = http.createServer(function(req, res){ // 1 設置cors跨域 res.setHeader("Access-Control-Allow-Origin", "*") res.setHeader("Access-Control-Allow-Headers", "Content-Type") res.setHeader("Content-Type", "application/json") // 2 switch (req.method) { case "OPTIONS": res.statusCode = 200 res.end() break case "POST": upload(req, res) break } }) function upload(req, res) { // 1 判斷 if (!isFormData(req)) { res.statusCode = 400 res.end("錯誤的請求, 請用multipart/form-data格式") return } // 2 處理 var form = new formidable.IncomingForm() form.uploadDir = "./myImage" form.keepExtensions = true form.on("field", (field, value) => { console.log(field) console.log(value) }) form.on("end", () => { res.end("上傳完成!") }) form.parse(req) } function isFormData(req) { let type = req.headers["content-type"] || "" return type.includes("multipart/form-data") } server.listen(3000) console.log("port is on 3000.")
用node app開啟http服務器后,在前端頁面中上傳一張kitty.jpg,我們看到控制臺打印出了前端上傳的imgName屬性:kitty.jpg
并且,myImage文件夾目錄下多了一張圖片:
打開一看,正是從前端上傳的那張kitty.jpg
文件改名我們發現,這個默認的文件名稱并不是我們想要的,我們想改成以當前時間戳命名的文件,添加的功能代碼如下:
var fs = require("fs") form.on("file", (name, file) => { // 重命名文件 let types = file.name.split(".") let suffix = types[types.length - 1] fs.renameSync(file.path, "./myImage/" + new Date().getTime() + "." + suffix) })
再次上傳,發現現在存的照片名稱已經變成我們想要的格式了。
Formidable的progress事件能給出收到的字節數,以及期望收到的字節數。我們可以借助這個做出一個進度條。
我們為上面的程序添加下面的代碼,每次有progress事件激發,就會計算百分比并用console.log()輸出:
form.on("progress", (bytesReceived, bytesExpected) => { var percent = Math.floor(bytesReceived / bytesExpected * 100) console.log(percent) })
再次上傳一張圖片,現在控制臺已經會打印出進度顯示了:
當然,一般情況下,我們是要把這個進度傳回到用戶的瀏覽器中去,這對于任何想要上傳大型文件的程序來說是個很棒的特性,并且這是個很適合用Node完成的任務。比如說用WebSocket協議,或者像Socket.IO這樣的實時模塊,關于Node中使用websocket,后面我會多帶帶出一篇文章來介紹。
錯誤處理任何時候都不要忘了對程序添加錯誤處理,如果你的程序在重要的時候崩掉了,可能輕則被老板打屁股,重則拉出去祭天。想象一下,如果用戶上傳的圖片很大,并且用戶的網絡還很慢,那么上傳的時間會超出前端代碼中設置的請求超時時間2s,服務器就會崩掉,不信?我們來試一下。
首先,我選擇了一張很大的圖片,5M,并且用chrome瀏覽器將瀏覽器網絡環境設置為slow 3g,設置方法如下:
f12打開開發者工具,在more tools--network conditions
點擊上傳,我們看見服務端控制臺的信息如下,服務器崩掉了:
所以,最后我們加上了錯誤處理,代碼如下:
// 加上錯誤處理,防止用戶網絡慢,或者取消上傳,導致服務器崩掉 form.on("error", err => { console.log(err) res.statusCode = 500 res.end("服務器內部錯誤!") })小結
現在,相信你已經學會了如何用Node處理文件上傳了,結合前面的那篇用Node提供靜態文件服務的文章,你是不是能夠自己摸索著去嘗試做一些有趣的事情了呢?
參考閱讀formidable文檔
input的file類型的accept屬性
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95986.html
摘要:執行安裝依賴項,然后執行啟動程序。模板的內容保存在內存中,性能會得到顯著提升。視圖查找當或被調用時,會先檢查是否有文件在這個絕對路徑上。代碼清單修改了之前的實現,給出照片被上傳時提供的名稱,比如 Express起步 安裝ExpressshowImg(https://segmentfault.com/img/bVXsFT?w=800&h=44); 一個最小的Express 程序showI...
摘要:常用的設置如下下的請求風格下的請求和不太一樣,在正式的請求發出之前都會先發一個類型為的請求作為試探,只有當該請求通過以后,正式的請求才能發向服務端。所以服務端路由我們還需要處理這樣一個請求注意該請求同樣需要設置跨域。 寫在前面 紅旗不倒,誓把JavaScript進行到底!今天介紹我的開源項目 Royal 里的圖片上傳組件的前后端實現原理(React + Node),花了一些時間,希望對...
摘要:前段時間面試過程中,頻繁遇到異步文件上傳的相關問題。所以,這會是一個拖放接口實現文件異步上傳的完整。監聽放置元素的事件,通過對象可以獲得拖拽事件的狀態及數據。后端文件接收保存后端使用實現文件上傳。 ??前段時間面試過程中,頻繁遇到H5異步文件上傳的相關問題。還遇到過一個通過H5拖放功能實現文件異步上傳的問題,大概知道H5有新增拖拽功能可以接收文件,如何異步上傳文件就母雞了(攤手)。面試...
閱讀 3166·2021-11-19 09:40
閱讀 3657·2021-11-16 11:52
閱讀 2987·2021-11-11 16:55
閱讀 3178·2019-08-30 15:55
閱讀 1183·2019-08-30 13:08
閱讀 1660·2019-08-29 17:03
閱讀 3018·2019-08-29 16:19
閱讀 2584·2019-08-29 13:43