🙆

HTML formタグのencTypeについて深掘りしてみる

に公開

はじめに

Web開発してると、必ずと言っていいほど登場するのがHTMLの<form>タグ。ユーザーからの情報をサーバーに送る、基本中の基本ですよね。でも、テキストだけじゃなくファイルを送ろうとした途端、「あれ?なんか上手く送れないぞ…?」ってなった経験があり、記事を書くことにしました。

その原因、もしかしたら<form>encType(エンクタイプ)属性の設定漏れや間違いかもしれません。

encTypeって、普段はあまり意識しないかもしれないけど、実はフォーム、特にファイルアップロードの成否を左右する重要な影の立役者なんです。

この記事では、「なんとなく知ってる」かもしれないencType属性について、基本からしっかり掘り下げていきます。それぞれの値が何をやっているのか、どう使い分けるのか、そしてファイルアップロードでなぜmultipart/form-dataが必須なのか等、調べたことを共有します。

encType属性って、そもそも何? - データ送信の「梱包ルール」を決めるやつ

encType属性は、フォームで入力されたデータがサーバーに送られるとき、どんな形式(ルール)で「梱包」して送るか を指定するための属性です。特に、method="post"でフォームを送信するときに意味を持ちます。

ブラウザはフォームデータをHTTPリクエストのボディに詰めて送るんですが、そのままだとサーバーが正しく解釈できないことがあるんですね。そこで、事前に「こういうルールでデータを整形・梱包しますよ」と決めておく必要があります。そのルールを指定するのがencTypeの役割です。

この梱包ルールが間違っていると、サーバー側で「荷解き」(デコード)がうまくできず、データが文字化けしたり、ファイルが正しく受け取れなかったりするわけです。

encTypeの3つの顔 - それぞれの役割と使い方

encTypeには、主に3つの指定方法があります。それぞれどんな性格で、どんな場面で活躍するのか見ていきましょう。

1. application/x-www-form-urlencoded - デフォルト

  • これが基本、デフォルトです。 encTypeを何も書かなければ、自動的にこれになります。
  • 仕事内容:
    • フォームのデータを「キー=値」のペアに変換。
    • 英数字以外の文字や記号は、URLエンコードというルールで安全な形(スペースは+に、特殊文字は%xxみたいに)変換します。
    • 各ペアを&で繋げて、一本の文字列にして送り出します。
    • 例: username=Tanaka+Taro&memo=%E3%83%A1%E3%83%A2%E3%81%A7%E3%81%99 (「メモです」がエンコードされている)
  • 得意なこと / 苦手なこと:
    • 名前やメールアドレスみたいな、普通のテキストデータを送るのは得意。
    • ファイル(画像とか)を送るのは苦手。 ファイルの中身までは送ってくれません。ファイル名くらいしか送れないんです。

2. multipart/form-data - ファイル送信のヒーロー

  • ファイルアップロードがあるなら、こいつの出番! 絶対に指定が必要です。
  • 仕事内容:
    • フォームデータを、いくつかの「パート」に分けて梱包します。まるで小包をいくつか作るイメージ。
    • 各パートには「これは〇〇という名前のテキストデータです」「これは△△というファイル名の画像データです」といったラベル(ヘッダー情報)が付きます。
    • テキストデータはそのまま、ファイルデータも中身をバイナリのまま、エンコードせずに梱包できます。
    • パートとパートの間は、特別な区切り文字(boundary)で仕切られます。
  • 得意なこと / 苦手なこと:
    • テキストもファイルも、ごちゃ混ぜにして送れるのが最大の強み。
    • ファイルアップロード機能を作るときは、指名必須の属性値です。これがないと始まりません。

3. text/plain - ちょっとマイナーな正直者?

  • 仕事内容:
    • データをほとんどエンコードせず、見た目に近い形で送ります。スペースはスペースのまま、改行もそのまま。
    • キーと値が=で結ばれ、各ペアが改行で区切られます。
    • 例:
      username=Yamada Hanako
      memo=テストメッセージ
      
  • 得意なこと / 苦手なこと:
    • 人間が見る分には、なんとなく分かりやすいかも…?
    • でも、特殊文字の扱いが曖昧だったり、サーバー側で「これ、どこからどこまでが一つの値?」ってなりがち。バグの温床になりやすいので注意が必要です。
    • 基本的にデバッグ用と考えた方が安全です。本番サービスで積極的に使う場面はほぼありません。ファイル送信も当然できません。

encTypeを使ってみよう - コードで見る違い

実際にコードでどう書くか見てみましょう。encType<form>タグに書きます。

application/x-www-form-urlencoded (デフォルト) - テキストだけならこれでOK

<form action="/user/profile" method="post">
  <label for="name">お名前:</label>
  <input type="text" id="name" name="username"><br>

  <label for="bio">自己紹介:</label>
  <textarea id="bio" name="userbio"></textarea><br>

  <button type="submit">更新</button>
</form>

👆 テキスト入力だけなら、特にencTypeを意識する必要はありません。

multipart/form-data - ファイルを送るなら必須!

<form action="/upload/image" method="post" enctype="multipart/form-data">
  <label for="title">タイトル:</label>
  <input type="text" id="title" name="image_title"><br>

  <label for="img">画像ファイル:</label>
  <input type="file" id="img" name="uploaded_image" accept="image/*"><br>

  <button type="submit">アップロード</button>
</form>

text/plain - (ほぼ)使わないけど一応…

<form action="/debug/formdata" method="post" enctype="text/plain">
   <label for="debug_msg">デバッグメッセージ:</label>
   <input type="text" id="debug_msg" name="debug_message"><br>

   <button type="submit">送信 (デバッグ用)</button>
</form>

ユースケース - じゃあ、結局いつどれを選ぶの?

シンプルに考えましょう。

フォームで送りたいものは? おすすめ encType 具体的な例
テキストや選択肢だけ application/x-www-form-urlencoded ログイン、検索、ユーザー設定、問い合わせフォーム、簡単なアンケートなど
ファイル(画像、PDFなど)を含む場合 multipart/form-data プロフィール画像変更、レポート提出、SNSへの写真投稿、ファイル共有機能など
ちょっと生のデータを見てみたい(デバッグ) text/plain サーバーに送られるデータ形式を一時的に確認したいとき(でも開発ツールの方が便利かも)

判断フローは超簡単:

  1. あなたのフォームに <input type="file"> はありますか?
    • YES! → 迷わず enctype="multipart/form-data"method="post" と一緒に指定!
    • NO! → 基本的に encType は書かなくてOK(デフォルトの application/x-www-form-urlencoded で十分)。text/plain は、よっぽどの理由がない限り忘れましょう。

【もう一歩踏み込む】encTypeの裏側とデバッグのコツ

基本は上記の通りですが、もう少し知っておくと「なるほど!」となるポイントをいくつか。

1. 開発ツールでネットワークリクエストを覗いてみよう!

これが一番分かりやすいです。ChromeやFirefoxの開発者ツールを開いて、「ネットワーク」タブを見ながらフォームを送信してみてください。

  • application/x-www-form-urlencoded だと、リクエストの Content-Type ヘッダーが application/x-www-form-urlencoded になり、「ペイロード」タブを見るとURLエンコードされた キー=値&キー=値 形式のデータが見えます。
  • multipart/form-data だと、Content-Typemultipart/form-data; boundary=----WebKitFormBoundary... のようになり、ペイロードを見ると、boundary 文字列で区切られたパートの中に、ファイル情報やファイルの中身(時にはバイナリで読めない形で)が見えるはずです。

この違いを実際に目で見ることで、「ああ、こういう風にデータが送られてるんだな」と実感できます。

2. サーバーサイドでの受け取り方が変わる!

送るデータの形式が違うということは、当然サーバー側での受け取り方(データの解釈方法)も変える必要があります。

  • application/x-www-form-urlencoded のデータは、多くのWebフレームワーク(Node.jsのExpressならexpress.urlencoded()ミドルウェア、PHPなら$_POST変数など)が、特別な設定なしに簡単に扱えるようになっています。
  • multipart/form-data のデータは、ファイルを含んでいる可能性があるため、専用の処理が必要です。例えばNode.js/Expressならmulterのようなミドルウェア、PHPなら$_FILES変数を使ってファイルデータを受け取ります。

サーバーサイドエンジニアは、フロントエンドの<form>で指定されたencTypeに合わせて、適切なデータ受け取り処理を実装しないといけません。もしフロントとサーバーで認識がズレていると、サーバー側で「データが空だぞ?」とか「ファイルが見当たらない!」といったエラーになるわけです。

まとめ - encTypeを制してフォームを制す!

encType属性は、フォームデータ送信の「梱包ルール」を決める大事なやつでした。

  • テキストだけならデフォルトの application/x-www-form-urlencoded でOK(指定不要)。
  • ファイル送信するなら、method="post"enctype="multipart/form-data" は絶対セットで指定! これ最重要!
  • text/plain は、まあ、忘れてもいいかも…。

encTypeを正しく使い分けるだけで、フォーム関連、特にファイルアップロード周りのトラブルはぐっと減るはずです。ぜひ開発ツールのネットワークタブも活用して、実際にどんなデータが送られているか確認してみてください。

Discussion