Multerの挙動調査
Express でいうところの Multer にあたる、Hono で multipart/form-data
を扱うライブラリ Hono Storage を開発しているが、いくつかテストで困ったので参考にするために Multer の挙動を確認していく。
今更Multer?と思うかもしれませんがそういうことです。
Interface
const upload = multer({ dest: "uploads/" });
dest
でexec pathからの相対パス or 絶対パスで保存先を設定できる
Single
const middleware = upload.single("file")
でmultipart/form-data
でPOSTされたデータのfile
フィールドが処理される
検証コード
app.post("/upload", upload.single("file"), (req, res) => {
const file = req.file;
console.log(file);
res.send("File uploaded successfully.");
});
Case 1 (ファイル単体)
ファイル -> 保存される
req.file
-> Multer.File
Case 2 (ファイル複数)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
req.file
-> unreachable
Case 3 (テキスト単体)
ファイル -> 保存されない
req.file
-> undefined
Case 4 (フィールドなし)
ファイル -> 保存されない
req.file
-> undefined
Case 5 (想定外のフィールド)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
Array
const middleware = upload.array("files", 2)
でmultipart/form-data
でPOSTされたデータのfiles
フィールドが処理される
第二引数がそのフィールドの最大要素数になっている
検証コード
app.post("/uploads", upload.array("files", 2), (req, res) => {
const files = req.files;
console.log(files);
res.send("Files uploaded successfully.");
});
Case 1 (複数ファイル)
ファイル -> 保存される
req.files
-> Multer.File[]
(全て)
Case 2 (複数テキスト)
ファイル -> 保存されない
req.files
-> Multer.File[]
(空)
Case 3 (複数ファイルと複数テキスト)
ファイル -> Filesだけ保存される
req.files
-> Multer.File[]
(Filesだけ)
Case 4 (複数ファイルでmaxCountをオーバーフロー)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
Case 5 (複数ファイルと複数テキストでmaxCountをオーバーフロー、ただしファイル数だけではオーバーフローしない)
ファイル -> Filesだけ保存される
req.files
-> Multer.File[]
(Filesだけ)
Case 6 (フィールドなし)
ファイル -> 保存されない
req.files
-> undefined
Case 7 (想定外のフィールド)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
Fields
const middleware = upload.fields([
{ name: "files", maxCount: 1 },
{ name: "images", maxCount: 8 },
]);
arrayを一つにまとめて書けるような感じ
シングルフィールドは定義できないみたい
検証コード
app.post(
"/fields",
upload.fields([
{ name: "file", maxCount: 1 },
{ name: "image", maxCount: 8 },
]),
(req, res) => {
const files = req.files;
console.log(files);
res.send("Files uploaded successfully.");
}
);
Case 1 (スキーマ通りのフィールド)
ファイル -> 保存される
req.files
-> Record<string, Multer.File[]>
(全て)
Case 2 (一部フィールドがない)
ファイル -> 一部保存される
req.files
-> Record<string, Multer.File[]>
(一部)
Case 3 (全部フィールドがない)
ファイル -> 保存されない
req.files
-> undefined
Case 4 (想定外のフィールド)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
Case 5 (一部フィールドがオーバーフロー)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
Case 6 (全部フィールドがオーバーフロー)
ファイル -> 保存されない
ミドルウェア内でErrorがthrowされる
None
const middleware = upload.none();
引数なし、multipart/form-data
にきたtext以外のフィールドを受け付けたくない時に使う
検証コード
app.post("/none", upload.none(), (req, res) => {
const body = req.body;
console.log(body);
res.send("Body received successfully.");
});
Case 1 (文字列のフィールド)
req.body
-> Record<string, string>
Case 2 (ファイルのフィールドあり)
ミドルウェア内でErrorがthrowされる
Case 3 (何もなし)
req.body
-> undefined
気づき・思ったこと
- Expressの代替を謳うHonoの障壁をなくすためにHono版Multerを作るのがコンセプト
- とりあえず挙動パクれるところはパクったほうが移行する側としては嬉しいかも
- Hono Storageでは現段階でエラー設計がそこまでできてないので、カスタムエラーを提供して
instance of
できるようにしたい
-
req.files
のキーがstringなので指定したフィールドの型補完が効かない -> HonoならVarsで渡せそう- そのためには
fields
を配列じゃなくてKVベースで定義しないと推論できなさそう - Multerのインターフェースとは異なってしまうけど移行ガイドを作ろう
- そのためには
-
req.none
いる????? -
maxCount
だけあってcount
とminCount
ないのはなんでなんだろう - middleware chainできない設計みたい
- midlleware chainサポートをすると想定外のフィールドが来たからエラーは技術的に難しそう
- contextでErrorを伝播して一番最後のstorage middlewareでErrorをDispatchする感じになるけどそこまで必要か
- Hono Storageは現状middleware chainをサポートしている代わりに、知らないフィールドがきてもエラーを吐かずにスルーしている
- midlleware chainサポートをすると想定外のフィールドが来たからエラーは技術的に難しそう
- アップロード結果のfilepathとれた方が嬉しいよね