Closed7

Multerの挙動調査

monicamonica

Express でいうところの Multer にあたる、Hono で multipart/form-data を扱うライブラリ Hono Storage を開発しているが、いくつかテストで困ったので参考にするために Multer の挙動を確認していく。

今更Multer?と思うかもしれませんがそういうことです。

monicamonica

Interface

const upload = multer({ dest: "uploads/" });

destでexec pathからの相対パス or 絶対パスで保存先を設定できる

monicamonica

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される

monicamonica

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される

monicamonica

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される

monicamonica

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

monicamonica

気づき・思ったこと

  • Expressの代替を謳うHonoの障壁をなくすためにHono版Multerを作るのがコンセプト
    • とりあえず挙動パクれるところはパクったほうが移行する側としては嬉しいかも
    • Hono Storageでは現段階でエラー設計がそこまでできてないので、カスタムエラーを提供してinstance ofできるようにしたい
  • req.filesのキーがstringなので指定したフィールドの型補完が効かない -> HonoならVarsで渡せそう
    • そのためにはfieldsを配列じゃなくてKVベースで定義しないと推論できなさそう
    • Multerのインターフェースとは異なってしまうけど移行ガイドを作ろう
  • req.noneいる?????
  • maxCountだけあってcountminCountないのはなんでなんだろう
  • middleware chainできない設計みたい
    • midlleware chainサポートをすると想定外のフィールドが来たからエラーは技術的に難しそう
      • contextでErrorを伝播して一番最後のstorage middlewareでErrorをDispatchする感じになるけどそこまで必要か
      • Hono Storageは現状middleware chainをサポートしている代わりに、知らないフィールドがきてもエラーを吐かずにスルーしている
  • アップロード結果のfilepathとれた方が嬉しいよね
このスクラップは3ヶ月前にクローズされました