吐槽express 中间件multer
工作不是那么忙,想學一下Express+multer弄一個最簡單的文件上傳,然后開始npm install,然后開始對著multer官方文檔一頓操作。
前臺頁面最簡單的:
<!DOCTYPE html> <html><head><style></style> </head><body><form action="/upload" method="POST" enctype="multipart/form-data"><input type="text" name="username" /><input type="file" name="avatar" /><input type="submit" value="提交"></form> </body></html>后臺服務啟用static靜態文件中間件,直接訪問,然后提交到/upload,后臺代碼如下:
const express = require('express') const multer = require('multer') const uuid = require('uuid/v4') const path = require('path') const port = 3000 const app = express() var storage = multer.diskStorage({destination: function (req, file, cb) {cb(null, path.join(__dirname, '../src/uploads'))},filename: function (req, file, cb) {console.log(file)let extName = path.extname(file.originalname)cb(null, uuid() + extName)} }) var upload = multer({storage: storage }) app.use(express.static('../src/test')) app.use('/upload', upload.single('avatar'), (req, res) => {// 處理上傳之后的邏輯 }) app.listen(port, () => {console.log('server is listening at ' + port) })就這么簡單,它就好像自動就給傳上去了,但是不足的地方也是存在的,比如默認配置下:它不給帶文件默認的擴展名,什么類型的也都接收,然后也不限制大小。
第一、首先說一下配置路徑和怎么給上傳之后的文件帶上默認擴展名。
upload = multer({}),multer初始化的時候,如果文件路徑dest不指定,那么官方文檔說文件路徑默認就是系統默認當前路徑做為文件存儲的臨時路徑,但是我嘗試之后,發現沒有報錯,但是文件給上傳到哪里去了,也不知道。滿臉黑線!!!
然后按照官方文檔,配置一下路徑吧,可以直接multer({dest:'路徑'}),也可以這樣:
var storage = multer.diskStorage({destination: function (req, file, cb) {cb(null, path.join(__dirname, '../src/uploads'))},filename: function (req, file, cb) {console.log(file)let extName = path.extname(file.originalname)cb(null, uuid() + extName)} }) var upload = multer({storage: storage })destination回調函數指定文件上傳路徑,也可以根據file的不同類型,區分不同的路徑,這邏輯都取決于你自己。filename也是回調函數,上傳文件怎么命名也都取決于你,它默認上傳后不給帶原文件擴展名,所以這部分就需要你自己給處理一下了,我這邊就先拿到文件原有的擴展名,然后給上傳之后的文件加上。
第二、使用fileFilter來過濾允許上傳的文件類型。
multer({})配置項中除了storage之外還給出了fileFIlter屬性,用來過濾允許上傳的文件,它也是一個函數,根據不同的文件后綴名來選擇是否允許通過。
var upload = multer({storage: storage,fileFilter: function (req, file, cb) {let extName = path.extname(file.originalname)if (extName.includes('.png')) {cb(null, true)} else {// req.fileCheckError = {}// req.fileCheckError['fileFilter'] = '只能上傳png格式的文件'cb(null, false)}} })通過cb(null,true),第二個參數是true和false來確定是否允許通過,然后官方文檔,還說第一個參數可以指定new Error來拋出一個錯誤,但是拋出錯誤之后,恐怕就需要另外寫express的錯誤事件處理了,否則后臺報錯,前臺是看不到東西的。官方又說話了,說multer自己不處理錯誤,它把錯誤委托給express處理了,然后用法就要變一變了,應該這樣:
app.use('/upload', upload.single('avatar'), (req, res) => {upload(req, res, function (err) {if (err instanceof multer.MulterError) {console.log(err, 'multer error') //處理multer自身的錯誤res.send(err)} else if (err) {console.log('normal error', err) // 處理委托給express和上傳時express自身的錯誤res.send(err.Error)} else if (Object.keys(req.fileCheckError || {}).length > 0) {console.log('req.fileCheckError', req.fileCheckError)res.send(JSON.stringify(req.fileCheckError))} else {console.log('req', req.file)let resContent = {}resContent['username'] = req.body.usernameresContent['filename'] = req.file.filenameres.send(resContent)}}) })這樣寫原以為cb(new Error("錯誤信息"),false)的錯誤信息會交給multer的錯誤處理呢,誰知道人家給委托給express的錯誤處理了,即便是這樣,它給的是一個錯誤,直接扔給前端,我想要的是一個友好的提示信息,而不是扔出一大坨錯誤信息,那就沒有辦法了嗎?
這個時候,有高手給出招了,說你既然中間件可以對req進行操作,為什么不對req中增加一個屬性呢?一句點醒夢中人,然后fileFilter中就給req加了fileCheckError,然后再express的錯誤處理的時候判斷一下,如果有,就友好的交給前端。
三、限制大小。
multer({limits:{}}),options里面有一個limits配置項,它同樣是一個對象里面有一堆配置的東西:
| fieldNameSize | Max field name size | 100 bytes |
| fieldSize | Max field value size | 1MB |
| fields | Max number of non-file fields | Infinity |
| fileSize | For multipart forms, the max file size (in bytes) | Infinity |
| files | For multipart forms, the max number of file fields | Infinity |
| parts | For multipart forms, the max number of parts (fields + files) | Infinity |
| headerPairs | For multipart forms, the max number of header key=>value pairs to parse | 2000 |
?
主要用到的也就是fileSize吧,超過設置大小,multer自動拋出錯誤到上面的multer自身處理錯誤中去,然后友好的發給前端就好了。
當然,以上說的這些錯誤,前端就可以判斷了,比如類型、大小,但是都說前端的校驗容易被篡改被突破,所以后端還是要校驗的,畢竟網絡安全無小事,萬一呢。
?
轉載于:https://www.cnblogs.com/liujiekun/p/11195913.html
總結
以上是生活随笔為你收集整理的吐槽express 中间件multer的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 03-spring bean
- 下一篇: os和sys模块的常用方法