題圖 By Clm From Bingjavascript
以前發過用nodejs搭建靜態服務器的文章,今天和你們探討一下如何利用nodejs接收前端上傳的文件。前端
首先咱們用nodejs的原生http模塊搭建一個服務器,而且利用data事件和end事件接收前端上傳的數據,代碼演示以下:java
const http = require("http");const app = http.createServer();const fs= require("fs");app.on("request",(req,res)=>{ if(req.method=="POST"){ var data = []; req.on("data",(chunk)=>{ data.push(chunk) }) req.on("end",()=>{ var buffer = Buffer.concat(data); fs.writeFile("./a",buffer,(err)=>{ if(!err){ res.end("ok") } }) }) }})app.listen(3000,()=>{ console.log("ok");})
閱讀源碼,咱們發現這段腳本將上傳的文件信息,寫入到了當前目錄的a文件中。node
看一下前端代碼,簡單的一個上傳文件的表單:typescript
<body> <form action="http://localhost:3000/" method="POST" enctype="multipart/form-data"> <input multiple type="file" name="a"> <input type="submit" value="提交"> </form> <script> </script></body>
點擊上傳後,服務端將接收到的全部信息寫入到了a文件中,打開a文件,截圖以下:
express
上面紅色部分就是圖片信息轉換爲utf-8字符串後的編碼,可是咱們要圖片,不要亂碼,怎麼辦呢?npm
咱們須要將這部分亂碼截取出來,再根據圖片的格式寫入到一個圖片文件中就能夠了,咱們須要作的是,咱們要提取圖片的二進制信息,提取圖片描述信息(大小、名稱、格式),將圖片輸出到須要長久保存的位置,本身手動實現的話比較麻煩。json
這部分邏輯已經有一些npm包幫我們實現了,今天就介紹兩個經常使用的。後端
首先看第一個npm包,也是我感受最好用的,fromidable,咱們集成formidable將上面服務器的代碼升級爲第二個版本,代碼以下:數組
const http = require("http");const app = http.createServer();const formidable = require("formidable");const path = require("path");app.on("request",(req,res)=>{ if(req.method=="POST"){ var form = new formidable.IncomingForm(); form.keepExtensions = true; form.multiples = true; console.log(form.type); form.uploadDir =path.join(__dirname,"my"); form.parse(req,function(err,fields,files){ res.end(JSON.stringify({fields,files})) }) }})app.listen(3000,()=>{ console.log("ok");})
仔細閱讀源碼,咱們發現formidable的使用很是簡單,以上代碼主要做用以下:
一、構造form對象
二、配置相關參數,好比長久保存文件的位置,上傳文件大小限制,是否容許上傳圖片數組。
三、調用form對象的parse方法解析文件信息,文件信息解析完成後會掛載到req上,文本信息將掛載到fileds上,文件信息將掛載到files上面。
四、根據fileds和files信息實現後端邏輯
五、將文件長久保存的地址返回給前端
比原生實現文件上傳簡單了不少,並且能夠根據需求配置不一樣的設置,formidable的經常使用配置以下:
new一個form實例var form = new formidable.IncomingForm()
將請求信息編碼設置爲utf-8form.encoding = 'utf-8';
設置文件的臨時存儲存儲路徑,若是不設置的話默認設置到 os.tmpdir()form.uploadDir = "/my/dir";
nodejs會默認將文件信息保存在一個沒有後綴的文件中,設置爲true將保留後綴form.keepExtensions = false;
<!-- 未知待測試 -->Either 'multipart' or 'urlencoded' depending on the incoming request.form.type
設置上傳信息-文本信息(fields)的的最大限制,默認是20mb,超出後會觸發form上的error事件form.maxFieldsSize = 20 * 1024 * 1024;
設置上傳信息-文件信息(file)的的最大限制,默認是200mb,超出後會觸發form上的error事件form.maxFileSize = 200 * 1024 * 1024;
設置上傳字符串的最大長度值爲1000;form.maxFields = 1000;
若是須要對上傳的文件進行校驗,須要設置sha1和md5,默認不校驗;form.hash = false;
若是前端表單設置了multiples,這個值須要設置爲true,後端接收的文件爲一個數組;form.multiples = false;
解析上傳的數據,將文本字段和文件從req中提取出來,fields存儲文本,files存儲文件form.parse(req, function(err, fields, files) { // ...});
以上即是今天介紹的nodejs上傳文件的第一個npm經常使用包formadable。
這個包也能夠結合express使用,由於express是對原生http模塊的封裝,因此咱們可使用form.parse直接解析express路由中的req信息,從而獲得前端傳遞的文件,或者結合express的中間件express-formidable,具體功能就不演示了,原理很是簡單,就是將formidable封裝成了一個express中間件而已,你們有興趣能夠去讀一下文檔。
接着看第二個經常使用的npm包,multer,這個插件是express的一箇中間件,express一、2版本中原本是集成到express中的,express3以後就分離出來了,因此要使用multer必須會使用express,這也是爲何把multer放到後面來說(小編真是用心良苦,今晚加雞腿)。
首先咱們打開multer的npm官網,先看他的自我介紹:
Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency. NOTE: Multer will not process any form which is not multipart (multipart/form-data)
https://www.npmjs.com/package/multer
翻譯成中文就是,multer只負責解析表單數據,也就是請求頭中攜帶content-type:multipart/form-data信息的請求才會處理,不然請注意multer不會運行。(小編的英語水平如何?)
multer的使用方式和formidable的使用方式很不同,使用步驟大體以下:
一、引入npm包multer,用一個變量來接受,假設變量爲multer
二、multer爲一個函數,這個函數調用後會返回一個對象,咱們用upload來接受這個對象,這個對象上面有好多生成express中間件的方法。
三、用upload這個生成中間件,放在相應位置去調用。
演示代碼以下:
var express = require('express');var multer = require('multer');// 生成一個對象,凡是用這個對象生成的中間件,文件都會保存到uploads文件中var upload = multer({ dest: 'uploads/' })// 生成中間件,只能處理avatar的文件,文件的name只能是avatar,不是的話會報錯var dealavatar = upload.single('avatar');var app = express()// 調用中間件app.post('/', dealavatar, function (req, res, next) { // req.file is the `avatar` file // req.body will hold the text fields, if there were any res.send({ fileds:req.body, files:req.file })})app.listen(3000,()=>{ console.log("ok");})
仔細閱讀源碼和註釋,咱們發現,multer中間件的配置分爲兩步:
一、第一步先調用multer函數傳遞一些參數,生成一箇中間件生成對象
二、對象在調用特定方法傳入特定參數,最終生成定製化的中間件。
那這樣的話,咱們想要熟練使用multer的話就須要知道
一、multer函數調用時須要傳遞哪些參數。
二、中間件生成對象有哪些方法能夠調用,而且須要傳遞哪些參數。
multer不一樣於formidbale的地方在於multer將全部接收到的信息都掛載到了req.body和req.file上面。
下面咱們就按照是上面提到的兩個問題,梳理一下multer的文檔,首先看第一個問題,multer須要傳遞哪些參數:
一、dest or storage 在哪裏存儲文件,dest比較直接,sotrage是存儲引擎,咱們能夠靈活的配置存儲引擎將文件進行保存 通常狀況下,使用dest便可,像這樣: var upload = multer({ dest: 'uploads/' })
二、fileFilter 設置一個函數來控制什麼文件能夠上傳以及什麼文件應該跳過,這個函數應該看起來像這樣:
function fileFilter (req, file, cb) {
// 這個函數應該調用 `cb` 用boolean值來 // 指示是否應接受該文件
// 拒絕這個文件,使用`false`,像這樣: cb(null, false)
// 接受這個文件,使用`true`,像這樣: cb(null, true)
// 若是有問題,你能夠老是這樣發送一個錯誤: cb(new Error('I don\'t have a clue!'))
}
三、limits 限制上傳的數據,是一個對象有以下可選項可供使用:
以上即是multer的參數,接下來看一下multer生成的中間件生成對象有哪些方法:
一、 .single(fieldname)
接受一個以 fieldname 命名的文件。這個文件的信息保存在 req.file。
2 、.array(fieldname[, maxCount])
接受一個以 fieldname 命名的文件數組。能夠配置 maxCount 來限制上傳的最大數量。這些文件的信息保存在 req.files。
三、 .fields(fields)
接受指定 fields 的混合文件。這些文件的信息保存在 req.files。fields 應該是一個對象數組,應該具備 name 和可選的 maxCount 屬性。
Example:[
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 8 }
]
四、.none()
只接受文本域。若是任何文件上傳到這個模式,將發生 "LIMIT_UNEXPECTED_FILE" 錯誤。這和 upload.fields([]) 的效果同樣。
五、.any()
接受一切上傳的文件。文件數組將保存在 req.files。
固然了使用multer咱們同樣要注意:永遠不要將 multer 做爲全局中間件使用,由於惡意用戶能夠上傳文件到一個你沒有預料到的路由,應該只在你須要處理上傳文件的路由上使用。
以上即是multer的使用了,multer還有不少其餘使用方式這裏沒有所有展現出來,畢竟篇幅有限,看文章讀到這裏的必定是真愛無疑了,小編一開始考慮將multer拆分出去的,可是這兩個玩意兒原本就一實現同一個功能的,研究的話乾脆就全研究了。
持續不斷的提供優質乾貨、心得、堅持作通俗易懂的技術訂閱號。
本文分享自微信公衆號 - nodejs全棧開發(geekclass)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。