# Multer處理檔案上傳 ###### tags: `MongoDB` `Nodejs` [Multer](https://www.npmjs.com/package/multer) npm i multer安裝後引入使用 ```javascript= // userRouter.js //***other things*** const multer = require('multer') const upload = multer({dest: 'public/img/users'}) // 上傳的資料儲存的資料夾 router.patch('/updateme', upload.single('photo'), userController.updateMe) // 將upload作為middleware使用,這邊的用法是上傳單張並存在photo這個key裡面 //***other things*** ``` 之後到updateMe新增console.log來測試 ```javascript= exports.updateMe = async (req, res, next) => { //***other things*** console.log(req.file) console.log(req.body) //***other things*** } ``` ## Postman測試上傳檔案 有別於JSON,上傳檔案要用formdata的形式來傳資料 postman在body的地方選form-data就可以了,可以選擇在該key要text還是file 還記得上面在middleware的設定嗎,所以這裡檔案的key要設定photo才能讓middleware接到 ![](https://i.imgur.com/i3ugFFg.png) 上傳成功後可以看一下server端剛剛加上去的log ![](https://i.imgur.com/ZciRurJ.png) 證明真的有被傳上去,但不會放在body中,因為body parser沒辦法處理檔案,這就是multer存在的意義(? 之後到對應路徑可以看到真的有被傳過去,不過目前直接傳會是binary檔案還沒辦法直接看 ![](https://i.imgur.com/5kxT0WH.png) ## Multer詳細設定 因為這種功能放在router很怪,所以先移到controller ```javascript= // userController.js const multer = require('multer') const upload = multer({dest: 'public/img/users'}) // 上傳的資料儲存的資料夾 exports.uploadUserPhoto = upload.single('photo') ``` ### multerStorage設定 可以去multer的github看storage的詳細說明 這裡先示範存在硬碟中的設定 ```javascript= const multerStorage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, 'public/img/users') }, filename: (req, file, cb) => { const ext = file.mimetype.split('/')[1] cb(null, `user-${req.user.id}-${Date.now()}.${ext}`) } }) ``` multer.diskStorage的option主要接收destination(儲存路徑)和filename(檔名) #### destination 產生路徑,透過他的callback(cb)產生 cb收兩個參數依序為(error, '路徑') #### filename 產生檔名,透過cb產生,cb接收的參數為(error, '檔名') 檔名的產生可以自己透過filename接進來的file和req來組合 例如我想存入 user-userID-timeStamp.jpg這種格式的檔案,就可以向上面的程式碼那樣寫 file接進來的東西就是在開頭測試的地方進來的req.file 所以可以用 const ext那種寫法來將副檔名分出來 而req就是一般的req ### Multerfiler設定 用來過濾檔案,例如我這用來過濾只給圖片檔過 ```javascript= const multerFilter = (req, file, cb) => { if(file.mimetype.startsWith('image')) { return cb(null, true) } cb(new ApiError('Only accet images', 400), false) } ``` ### upload整合 將上面做的設定放到multer()裡 ```javascript= const upload = multer({ storage: multerStorage, fileFilter: multerFilter }) ``` 再次測試發現file裡面的filename已經是我們組合過的結果 ![](https://i.imgur.com/6Sq8Xhe.png) 而且圖片也看得到了 ![](https://i.imgur.com/YNDzHAb.png) ## 複數檔案上傳