# 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接到

上傳成功後可以看一下server端剛剛加上去的log

證明真的有被傳上去,但不會放在body中,因為body parser沒辦法處理檔案,這就是multer存在的意義(?
之後到對應路徑可以看到真的有被傳過去,不過目前直接傳會是binary檔案還沒辦法直接看

## 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已經是我們組合過的結果

而且圖片也看得到了

## 複數檔案上傳