Node.js側で multipart/form-data を受信できない原因・解決策

今回遭遇したのは次のような問題

  • Node.js側でPOST受信するPOST APIを定義
  • クライアント側からそのAPIにPOST送信する
  • その際FormDataによりデータを渡したい
  • 上手くいかないので悩む…

POST送信する時にデータを渡すのですが、
それに multipart/form-data を使ってました。

ところがNode.js側でそれを受け取れてません。

その解決策が分かったのでメモしておきます。

クライアントからFormDataでPOST送信したが…

ちょうど次のような状況です。

▼ クライアント側 : POST送信コード例

▼ Node.js側 : Post送信のRouter

このコードには2つほど間違いがありました。

そもそもNode.js / Express ではFormDataを標準的にサポートしていないようです。だからFormDataでPost送信しても req.body には未解析のデータが入っています。

それを解析できるモジュールが必要ということ

FormDataを扱えるNode.jsモジュールを探した

探してみると色々なモジュールがあります。

▼ FormData解析用のモジュール候補

結論から言うと express-formidable を選びました、

どうしてかというと環境的な要因もあるのか、他4つは正常に機能しなかったからです。あと express-formidable は使い方もシンプルで分かりやすいから

npm経由でexpress-formidableをインストール

ということでnpmからインストールします。

▼ npmからexpress-formidableをインスト

ちなみにライセンスはMITで配布されてます。

受信したmultipart/form-dataを解析する

これでNode.js側でFormDataが解析できます。

具体的には次の2つが手に入ります。

  • request.fields  : 送信された非file以外のデータ
  • request.files  : 送信されたfilesのデータ

そして先ほどのRouterコードを改良しました。

▼ このようなコードに改良

POST送信されたFormDataを受け取りに成功!

全体ではなく個別Routerに適用できるのも便利です。

FormData送信時はContent-Type指定してはダメ

あとfetch送信時などに重要なことが1つ

それはContent-Typeを指定しないこと

だから以下のようなコードに修正しました。

▼ クライアント側 : fetchによるコードも改良

そうしないとexpress-formidableがエラーを吐きます。

 

なんでContent-Typeを指定してはいけないのか…
その理由はここに書くより次記事を見るのが早いです。

▼ FormDataをPOSTするときにContent-Typeを指定しない

多分Ajaxとか他APIでも同様かと思います。

この点にも注意が必要ですね。

Node.jsでFormData受信するポイントまとめ

ということで簡単にまとめます。

  • Node自体はmultipart/form-dataに未対応
    正確に書くならNode.js / Express ではFormDataにより送られた multipart/form-data のデータは解析できない。受信するには express-formidable のようなモジュール必要
  • クライアント側でContent-Type指定は不要
    それからクライアント側からFormDataを使ってNode側に送信する場合、Fetch API などでContent-Typeを指定してはいけない(Ajaxなど他APIでも同様)

この2点に注意しておけば大丈夫かと

以上、Node.jsで multipart/form-data を受信するでした。

もし間違ってる点などあれば教えてください。ではまた