HTMLフォームでenctype='multipart/form-data'
とはどういう意味ですか、いつ使用するべきですか?
POSTリクエストを行うときは、リクエストの本体を形成するデータを何らかの方法でエンコードする必要があります。
HTMLフォームは3つのエンコード方法を提供します。
application/x-www-form-urlencoded
デフォルト)multipart/form-data
text/plain
application/json
を追加する作業は行われていましたが、それは放棄されました。
(HTMLフォーム送信以外の手段を使用して生成されたHTTP要求では、他のエンコードも可能です。)
フォーマットの詳細は、ほとんどの開発者にとって重要ではありません。重要な点は次のとおりです。
text/plain
を使用しないでください。クライアントサイドコードを書くとき:
multipart/form-data
要素が含まれている場合は<input type="file">
を使用してくださいmultipart/form-data
またはapplication/x-www-form-urlencoded
を使用できますが、application/x-www-form-urlencoded
の方が効率的です。サーバーサイドコードを書くとき:
ほとんどのもの(PerlのCGI->param
やPHPの$_POST
superglobalによって公開されているものなど)は、その違いを処理します。サーバーが受け取った生の入力をパースしようとしないでください。
時にはあなたは両方のフォーマットを扱うことができないライブラリを見つけるでしょう。フォームデータを扱うためのNode.jsの最も人気のあるライブラリは body-parser です。
生データを解析または生成するためのライブラリを作成(またはデバッグ)している場合は、フォーマットについて心配する必要があります。あなたはまた興味のためにそれについて知りたいと思うかもしれません。
application/x-www-form-urlencoded
は、URLの最後にあるクエリ文字列とほぼ同じです。
multipart/form-data
はかなり複雑ですが、ファイル全体をデータに含めることができます。結果の例は HTML 4 specification にあります。
text/plain
はHTML 5で導入されたもので、デバッグにのみ有用です。 the spec :_から。(これらはcomputerでは確実に解釈できません。ほとんどのブラウザの開発者向けツールはそれに向いています。
いつ使うべきか
Quentinの答えは正しいです。フォームにファイルのアップロードが含まれる場合はmultipart/form-data
を、それ以外の場合はapplication/x-www-form-urlencoded
を使用します。enctype
を省略した場合はこれがデフォルトになります。
私はするつもりだ:
enctype
には 3つの可能性 があります:
application/x-www-form-urlencoded
multipart/form-data
(specは RFC7578 )を指していますtext/plain
。これは「コンピュータでは確実に解釈できない」ので、本番環境では決して使用しないでください。これ以上は検討しません。それぞれの方法の例を見れば、それらがどのように機能するか、そしていつそれぞれを使用すべきかが明らかになります。
あなたは例を使って例を作り出すことができます:
nc -l
またはECHOサーバー: GET/POSTリクエストを受け付けるHTTPテストサーバーフォームを最小限の.html
ファイルに保存します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
デフォルトのテキスト値をaωb
に設定します。これは、aωb
はω
であり、これはUTF-8のバイトU+03C9
であるため、61 CF 89 62
を意味します。
アップロードするファイルを作成します。
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
私たちの小さなエコーサーバーを実行します。
while true; do printf '' | nc -l 8000 localhost; done
ブラウザでHTMLを開き、ファイルを選択して送信をクリックして端末を確認してください。
nc
は受け取った要求を表示します。
テスト済み:Ubuntu 14.04.3、nc
BSD 1.105、Firefox 40。
Firefoxが送信しました:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
バイナリファイルとテキストフィールドの場合、バイト61 CF 89 62
UTF-8のaωb
)は文字通りに送信されます。 nc -l localhost 8000 | hd
を使ってそれを検証することができます。
61 CF 89 62
送信されました(61
== 'a'および62
== 'b')。
したがって、次のことが明らかです。
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
は、コンテンツタイプをmultipart/form-data
に設定し、フィールドが指定されたboundary
文字列で区切られていることを示します。
すべてのフィールドはそのデータの前にいくつかのサブヘッダーを取得します:Content-Disposition: form-data;
、フィールドname
、filename
、そしてデータ。
サーバーは次の境界ストリングまでデータを読み取ります。ブラウザはどのフィールドにも表示されない境界を選択する必要があるため、境界が要求によって異なる可能性があります。
独自の境界があるため、データのエンコードは不要です。バイナリデータはそのまま送信されます。
TODO:最適な境界サイズ(log(N)
)、それを見つけたアルゴリズムの名前/実行時間は?で尋ねた:_(https://cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type
はブラウザによって自動的に決定されます。
enctype
をapplication/x-www-form-urlencoded
に変更し、ブラウザをリロードして、再送信してください。
Firefoxが送信しました:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
明らかにファイルデータは送信されず、ベースネームのみが送信されました。したがって、これはファイルには使用できません。
テキストフィールドに関しては、a
やb
のような通常の印刷可能文字が1バイトで送信され、0xCF
や0x89
のような印刷不可能文字は 3バイト each:%CF%89
!
ファイルのアップロードには印刷できない文字(画像など)が多く含まれていますが、テキスト形式ではほとんど含まれていません。
例から私達はそれを見た:
multipart/form-data
:メッセージに数バイトの境界オーバーヘッドを追加し、それを計算するのにしばらく時間を費やす必要がありますが、各バイトを1バイトで送信します。
application/x-www-form-urlencoded
:フィールドごとに1バイト境界(&
)がありますが、すべての非印刷可能文字について、 3x のlinearオーバーヘッド係数が追加されます。
したがって、たとえapplication/x-www-form-urlencoded
を付けてファイルを送信できたとしても、やりたくないでしょう。それはとても非効率的だからです。
しかし、テキストフィールドにある印刷可能な文字については、それは問題ではなく、オーバーヘッドも少なくなるので、ここで使用しています。
enctype='multipart/form-data
は、 _ post _ を介してファイルを送信できるようにするエンコーディングタイプです。簡単に言うと、このエンコーディングがないと、ファイルは _ post _ を介して送信できません。
ユーザーがフォームを介してファイルをアップロードできるようにしたい場合は、 enctype を使用する必要があります。
フォームを送信するときは、HTTPプロトコルを介して、TCP/IPプロトコルのメッセージ構造に正しく包まれたネットワーク上のメッセージを送信するようにブラウザに指示します。 HTMLページには、<form>
sを使用してサーバーにデータを送信する方法があります。
フォームが送信されると、HTTPリクエストが作成されてサーバーに送信されると、メッセージにはフォーム内のフィールド名とユーザーが入力した値が含まれます。この転送はPOST
またはGET
HTTPメソッド で発生する可能性があります。
POST
は、HTTPメッセージを作成し、すべてのコンテンツをメッセージの本文に入れるようにブラウザに指示します(非常に便利な方法で、より安全で柔軟です)。GET
は クエリ文字列 でフォームデータを送信します。データの表現と長さに関していくつかの制約があります。属性enctype
は、POST
メソッドを使用する場合にのみ意味があります。指定すると、ブラウザはそのコンテンツを特定の方法でエンコードしてフォームを送信するように指示します。 From MDN - フォームenctype :
Method属性の値がpostの場合、enctypeはフォームをサーバーに送信するために使用されるコンテンツのMIMEタイプです。
application/x-www-form-urlencoded
:これはデフォルトです。フォームが送信されると、すべての名前と値が収集され、最後の文字列に対して URL Encoding が実行されます。multipart/form-data
:文字はエンコードされていません。フォームにファイルアップロードコントロールがある場合、これは重要です。あなたはファイルバイナリを送りたいと思うでしょう、そしてこれはビットストリームが変更されないことを確実にします。text/plain
:スペースは変換されますが、それ以上エンコードは実行されません。フォームを送信するとき、 RFC 7578セクション7:マルチパートフォームデータ - セキュリティに関する考慮事項 :に記載されているように、セキュリティ上の問題が発生する可能性があります。
すべてのフォーム処理ソフトウェアはユーザー提供のフォームデータを扱うべきです
機密情報または個人情報が含まれることが多いため、慎重に
識別情報Webブラウザではフォームの「自動入力」機能が広く使用されています。これらはユーザをだましてしまうために使われるかもしれません
そうでない場合は、知らないうちに機密情報を送信する
無害な仕事multipart/form-dataは機能を提供しません
完全性の確認、機密性の確保、ユーザーの回避
混乱、またはその他のセキュリティ機能これらの懸念は
フォーム記入およびフォームデータ解釈アプリケーションによって対処されます。フォームを受信して処理するアプリケーションは、送信を意図していない要求元のフォーム処理サイトにデータを返さないように注意する必要があります。
コンテンツのファイル名を解釈するときに重要です。
不注意でファイル内のファイルを上書きしないようにするための処置ヘッダーフィールド
受信者のファイルスペース.
あなたが開発者であり、あなたのサーバーがユーザーから送信された機密情報を含む可能性のあるフォームを処理する場合、これはあなたに関係します。
enctype='multipart/form-data'
は、文字がエンコードされないことを意味します。これが、ファイルをサーバーにアップロードするときに使用される理由です。
したがって、ファイルの内容などのバイナリデータをアップロードするためにフォームにバイナリデータが必要な場合は、multipart/form-data
を使用します
フォームを使用してファイルの内容をURLパラメータ内に配置することはできないため、method属性をPOSTに設定します。
データは複数の部分に分割されるため、enctypeの値をmultipart/form-dataに設定します。1つはファイルごとに、もう1つはそれらと共に送信される可能性のあるフォーム本体のテキスト用です。
通常、ファイルアップロードをデータとして受け取る必要があるPOSTフォームがある場合です。転送されたデータをエンコードする方法をサーバーに通知します。このような場合はエンコードされません。例えば画像やpdfをアップロードするときのように、ファイルをサーバーに転送してアップロードするだけです。