enctype='multipart/form-data'
HTML フォームの意味と、それをいつ使用する必要があるか?
10 に答える
POST リクエストを行う場合、リクエストのボディを形成するデータを何らかの方法でエンコードする必要があります。
HTML フォームには、3 つのエンコード方法があります。
application/x-www-form-urlencoded
(デフォルト)multipart/form-data
text/plain
を追加する作業が行われていましapplication/json
たが、それは放棄されました。
(HTML フォーム送信以外の手段を使用して生成された HTTP 要求では、他のエンコーディングが可能です。JSON は Web サービスで使用される一般的な形式であり、一部はまだ SOAP を使用しています。)
形式の詳細は、ほとんどの開発者にとって重要ではありません。重要な点は次のとおりです。
- 絶対に使用しないでください
text/plain
。
クライアント側のコードを記述する場合:
multipart/form-data
フォームに<input type="file">
要素が含まれている場合に使用します- それ以外の場合は
multipart/form-data
orを使用できますapplication/x-www-form-urlencoded
がapplication/x-www-form-urlencoded
、より効率的になります
サーバー側のコードを書いている場合:
- 事前に作成されたフォーム処理ライブラリを使用する
ほとんど (Perl のCGI->param
ものや PHP の$_POST
スーパーグローバルによって公開されているものなど) は、違いを処理してくれます。サーバーが受け取った生の入力をわざわざ解析しようとしないでください。
場合によっては、両方の形式を処理できないライブラリが見つかることがあります。フォーム データを処理するための Node.js の最も一般的なライブラリは、マルチパート リクエストを処理できないbody-parserです (ただし、可能ないくつかの代替手段を推奨するドキュメントがあります)。
生データを解析または生成するためのライブラリを作成 (またはデバッグ) している場合は、フォーマットについて心配する必要があります。また、興味のためにそれについて知りたいと思うかもしれません。
application/x-www-form-urlencoded
URL の末尾にあるクエリ文字列とほぼ同じです。
multipart/form-data
はかなり複雑ですが、ファイル全体をデータに含めることができます。結果の例は、HTML 4 仕様にあります。
text/plain
は HTML 5 で導入され、デバッグにのみ役立ちます —仕様から:それらはコンピューターによって確実に解釈可能ではありません— ツールと組み合わせた他のもの (ほとんどのブラウザーの開発者ツールのネットワーク パネルなど) の方が優れていると私は主張しますそのために)。
いつ使用する必要がありますか?
クエンティンの答えは正しいです。multipart/form-data
フォームにファイルのアップロードが含まれている場合は使用し、application/x-www-form-urlencoded
それ以外の場合は省略した場合のデフォルトですenctype
。
私はするつもりだ:
- HTML5 参照をさらに追加する
- フォーム送信の例で彼が正しい理由を説明してください
HTML5 リファレンス
には3 つの可能性がありenctype
ます。
application/x-www-form-urlencoded
multipart/form-data
(仕様はRFC7578を指しています)text/plain
. これは「コンピューターで確実に解釈できない」ため、本番環境では使用しないでください。これ以上調査することはありません。
サンプルの生成方法
各メソッドの例を見ると、それらがどのように機能するか、およびそれぞれをいつ使用する必要があるかが明らかになります。
以下を使用して例を作成できます。
nc -l
または ECHO サーバー: GET/POST 要求を受け入れる HTTP テスト サーバー- ブラウザや cURL のようなユーザー エージェント
フォームを最小限の.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
これは、 UTF-8のバイトである であるaωb
ためです。ω
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 localhost 8000; 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
( aωb
UTF-8) は文字どおりに送信されます。でそれを確認できnc -l localhost 8000 | hd
ます。これは、バイトが次のことを示しています。
61 CF 89 62
送信されました ( 61
== 'a' および62
== 'b')。
したがって、次のことは明らかです。
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
コンテンツ タイプを に設定multipart/form-data
し、フィールドが指定されたboundary
文字列で区切られていることを示します。ただし、次のことに注意してください。
boundary=---------------------------735323031399963166993862150
--
実際のバリアよりダッシュが 2 つ少ない-----------------------------735323031399963166993862150
これは、標準では境界を 2 つのダッシュで開始する必要があるため
--
です。他のダッシュは、Firefox が任意の境界を実装するために選択した方法のようです。RFC 7578では、先頭の 2 つのダッシュが必要であることが明確に述べられています。--
4.1. multipart/form-data の「境界」パラメータ
他のマルチパート タイプと同様に、パートは境界区切り文字で区切られ、CRLF、「--」、および「境界」パラメータの値を使用して構築されます。
すべてのフィールドは、そのデータの前にいくつかのサブヘッダーを取得します:
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-sequencesContent-Type
ブラウザによって自動的に決定されます。正確にどのように決定されるかは、次の場所で尋ねられました:アップロードされたファイルの mime タイプはブラウザーによってどのように決定されますか?
application/x-www-form-urlencoded
を に変更し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
な文字はそれぞれ3 バイト0x89
を占めていることがわかります。%CF%89
比較
ファイルのアップロードには、多くの場合、印刷できない文字 (画像など) が含まれていますが、テキスト フォームにはほとんど含まれていません。
例から、次のことがわかりました。
multipart/form-data
: 数バイトの境界オーバーヘッドがメッセージに追加され、その計算にある程度の時間を費やす必要がありますが、各バイトは 1 バイトで送信されます。application/x-www-form-urlencoded
: フィールドごとに 1 バイトの境界があります ( ) が、印刷できない文字ごとに3 倍の線形オーバーヘッド係数&
が追加されます。
したがって、 でファイルを送信できたとしても、application/x-www-form-urlencoded
非常に効率が悪いため、送信したくありません。
しかし、テキスト フィールドで見つかった印刷可能な文字の場合は問題ではなく、生成されるオーバーヘッドも少ないため、そのまま使用します。
enctype='multipart/form-data
ファイルをPOST経由で送信できるようにするエンコーディング タイプです。簡単に言えば、このエンコーディングがないと、ファイルをPOSTで送信できません。
ユーザーがフォーム経由でファイルをアップロードできるようにする場合は、このenctypeを使用する必要があります。
フォームを送信するとき、TCP/IP プロトコル メッセージ構造に適切にエンベロープされたメッセージを HTTP プロトコル経由でネットワーク上に送信するようにブラウザに指示します。HTML ページには、サーバーにデータを送信する方法があります<form>
。
フォームが送信されると、HTTP リクエストが作成されてサーバーに送信されます。メッセージには、フォーム内のフィールド名とユーザーが入力した値が含まれます。この送信はPOST
またはGET
HTTP メソッドで発生する可能性があります。
POST
HTTP メッセージを作成し、すべてのコンテンツをメッセージの本文に入れるようにブラウザに指示します (物事を行うための非常に便利な方法であり、より安全で柔軟でもあります)。GET
querystringでフォーム データを送信します。データの表現と長さに関していくつかの制約があります。
フォームをサーバーに送信する方法を記述する
属性は、メソッドenctype
を使用する場合にのみ意味があります。POST
指定すると、特定の方法でコンテンツをエンコードしてフォームを送信するようブラウザに指示します。MDNから- フォーム enctype :
method 属性の値が post の場合、enctype はフォームをサーバーに送信するために使用されるコンテンツの MIME タイプです。
application/x-www-form-urlencoded
: これがデフォルトです。フォームが送信されると、すべての名前と値が収集され、最終的な文字列に対してURL エンコードが実行されます。multipart/form-data
: 文字はエンコードされません。これは、フォームにファイル アップロード コントロールがある場合に重要です。ファイル バイナリを送信する場合、これにより、ビットストリームが変更されないことが保証されます。text/plain
: スペースは変換されますが、それ以上のエンコードは実行されません。
安全
フォームを送信すると、 RFC 7578 セクション 7: マルチパート フォーム データ - セキュリティに関する考慮事項 に記載されているように、セキュリティ上の問題が発生する可能性があります。
すべてのフォーム処理ソフトウェアは
、機密情報や個人
を特定する情報が含まれていることが多いため、ユーザーが提供するフォーム データを慎重に扱う必要があります。Web ブラウザーでは、フォームの「自動入力」機能が広く使用されています。 これらは、他の方法では無害なタスクを完了しているときに、ユーザーをだまして
無意識のうちに機密情報を送信させるために使用される可能性があります。 multipart/form-data は、整合性のチェック、機密性の確保、ユーザー の混乱の回避、またはその他のセキュリティ機能のため
の機能を提供しません。 これらの問題は、フォーム入力アプリケーションとフォーム データ解釈アプリケーションで対処する必要があります。フォームを受信して処理するアプリケーションは、送信を意図していないフォーム処理サイトにデータを返さないように注意する必要があります。
Content-Disposition ヘッダー フィールドのファイル名を解釈するときに、 受信者のファイル スペース内の
ファイルを誤って上書きしないようにすることが重要です。
これは、あなたが開発者であり、サーバーがユーザーによって送信されたフォームを処理し、最終的に機密情報が含まれる可能性がある場合に関係します。
enctype='multipart/form-data'
文字がエンコードされないことを意味します。そのため、ファイルをサーバーにアップロードするときにこのタイプが使用されます。
Somultipart/form-data
は、フォームがファイルのコンテンツなどのバイナリ データをアップロードする必要がある場合に使用されます。
- enctype( ENC ode TYPE ) 属性は、サーバーに送信するときにフォームデータをエンコードする方法を指定します。
- multipart/form-data は enctype 属性の値の 1 つで、ファイルのアップロードを持つフォーム要素で使用されます。マルチパートとは、フォームデータが複数のパートに分割されてサーバーに送信されることを意味します。
通常、これは、ファイルのアップロードをデータとして取得する必要がある POST フォームがある場合です...これにより、転送されたデータをエンコードする方法がサーバーに通知されます。このような場合、転送してアップロードするだけであるため、エンコードされません。たとえば、画像やPDFをアップロードするときのように、サーバーへのファイル