最近はサーバサイドもTypeScriptにしていて、
routing-controllersがいい感じ。
ファイルアップロードを扱う際は、expressjs/multerを利用するけど、
若干ハマったので、そのときの備忘録。
やりたかったこと
- 複数のファイルを同時にアップロードしたい
- それぞれは
one
/two
というフィールド名 - 各フィールドは1つで、必須ではない(0でもOK)
routing-controllersでは、こんな感じでデコレータをつけるけど、
必須ではない複数フィールドではうまくいかないっぽい。。
@Post("/files") saveFile(@UploadedFile("fileName") file: any) { }
問題の原因
routing-controllersのissueだとこのあたり。
- How to upload files with mutiple field with routing controller guys ? · Issue #393 · typestack/routing-controllers
- Unclear error message "MulterError: Unexpected field" · Issue #799 · expressjs/multer
multerではいくつか関数が用意されているが、それぞれ制約が異なる。
また、routing-controllersでは、single
とarray
が対応している。
Multer function | Files accepted | n | decorator |
---|---|---|---|
multer.none() | 0 | 0 | |
multer.any() | 0+ | n | |
multer.single() | 1 | 1 | @UploadedFile |
multer.array() | 1+ | >=1 | @UploadedFiles |
multer.fields() | 1+ | >=1 |
なので、
@UploadedFile
と@UploadedFiles
は1つしか使えない- 必ず指定が必要(必須になる)
という条件がある。
解決策
複数フィールドでどちらも必須の場合
どちらも必須であれば、multer.fields()
を利用することができるので、
@UseBefore
を使い、@Req()
から取得すればOK
import { Request } from "express"; import multer from "multer"; @Post() @UseBefore(multer.fields([{ name: 'one', maxCount: 1 }, { name: 'two', maxCount: 1 }])) action(@Req() req: Request) { const fileOne = req.files['one'][0]; const fileTwo = req.files['two'][0]; }
複数フィールドで任意の場合
0個にも対応しているのは、multer.any()
のみなので、
@UseBefore(multer.any())
を利用する。
.fieldname
でフィールド名が取得できるので、
req.files.find()
で対象のフィールド名のファイルを取得する形。
import { Request } from "express"; import multer from "multer"; @Post() @UseBefore(multer.any()) action(@Req() req: Request) { const fileOne = req.files?.find(v => v.fieldname == "one") || null; const fileTwo = req.files?.find(v => v.fieldname == "two") || null; }
以上!! routing-controllersもmulterも便利だけど、
うまくいかないと深いとこまで調べないといけないのがつらい(´・ω・`)
参考にしたサイト様
- typestack/routing-controllers: Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage in Express / Koa using TypeScript and Routing Controllers Framework.
- How to upload files with mutiple field with routing controller guys ? · Issue #393 · typestack/routing-controllers
- Unclear error message "MulterError: Unexpected field" · Issue #799 · expressjs/multer