multipart/form-dataについて質問したいと思います。HTTPヘッダの中には、
Content-Type: multipart/form-data; boundary=??
この ???
はユーザーが自由に定義できるものですか?それとも、HTMLから生成されるのでしょうか?を定義することは可能ですか?= abcdefg`?
???
は、ユーザーが自由に定義できるのでしょうか?
はい。
それとも、HTMLから供給されるのですか?
いいえ、HTMLは、何も関係ありません。以下をお読みください。
???
をabcdefg
と定義することは可能でしょうか?
はい。
以下のようなデータをWebサーバーに送信したいとします。
name = John
age = 12
を application/x-www-form-urlencoded
を使って送信すると、以下のようになります。
name=John&age=12
ご覧のとおり、サーバはパラメータがアンパサンド &
で区切られていることを認識しています。もし、パラメータの値に &
が必要な場合は、それをエンコードする必要があります。
では、multipart/form-data
を使ったHTTPリクエストを受信したとき、サーバはどのようにしてパラメータ値の始まりと終わりを知るのでしょうか?
&`と同様に、境界線を使用します。
例えば、以下のようになります。
--XXX
Content-Disposition: form-data; name="name"
John
--XXX
Content-Disposition: form-data; name="age"
12
--XXX--
この場合、境界値は XXX
となります。これをContent-Type
ヘッダーで指定することで、サーバーは受信したデータを***どのように分割するかを知ることができます。
だから必要なのです。
サーバーに送信されるHTTPデータには現れない値を使用する。
一貫性を持たせ、リクエストメッセージ内のどこでも同じ値を使用する。
この質問に対する正確な答えは以下の通りです。はい、長さが70バイトを超えず、7ビットのUS-ASCII
(印刷可能な)文字のみで構成されていれば、boundary
パラメータに任意の値を使用することができます。
multipart/コンテントタイプのいずれかを使用している場合は、実際には
Content-Typeヘッダーで
boundary` パラメータを指定することが 必須* です。
また、ペイロードのデータには US-ASCII
のみが使用されると 絶対に 確信できる場合を除き、Content-Type
ヘッダの charset
パラメータには UTF-8
を設定したいと思うでしょう。
RFC2046]から関連する部分をいくつか抜粋します。
4.1.2.charsetパラメータ。 4.1.2. Charsetパラメータ: > 他のいくつかのパラメータ値とは異なり、charsetパラメータの値は大文字小文字を区別しません。 charsetパラメータがない場合に想定されるデフォルトの文字セットはUS-ASCIIです。
5.1. マルチパートメディアタイプ
Content-Transfer-Encodingフィールドの定義[RFC 2045]にあるように、"multipart"タイプのエンティティには、"7bit"、"8bit"、または"binary"以外のエンコードは許されません。 multipart"のバウンダリデリミタとヘッダーフィールドは、どのような場合でも7ビットのUS-ASCIIで表現されます(ただし、ヘッダーフィールドはRFC2047に従ってUS-ASCII以外のヘッダーテキストをエンコードすることができます)。また、ボディパーツ内のデータは、適切なボディパーツごとにContent-Transfer-Encodingフィールドを使用して、パーツごとにエンコードすることができます。
マルチパートのContent-Typeフィールドには、"boundary"という1つのパラメータが必要です。境界線は、2つのハイフン("-"、10進数で45)、Content-Typeヘッダーフィールドの境界線パラメータ値、オプションの線形ホワイトスペース、および終了のCRLFで構成される行として定義されます。
バウンダリ・デリミタは、カプセル化された素材の中にあってはならず、先頭の2つのハイフンを除いて70文字以下でなければなりません。
最後のボディパーツに続く境界線は、それ以上のボディパーツが続かないことを示す区別されたデリミタです。 このような区切り線は、前の区切り線と同じですが、境界パラメータ値の後にさらに2つのハイフンが追加されます。
以下は、任意の境界を使用した例です。
Content-Type: multipart/form-data; charset=utf-8; boundary="another cool boundary"
--another cool boundary
Content-Disposition: form-data; name="foo"
bar
--another cool boundary
Content-Disposition: form-data; name="baz"
quux
--another cool boundary--
"Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types"
multipart/form-dataには、名前と値のペアを分離するための境界が含まれています。バウンダリは、フォームが送信されたときに渡される名前と値のペアの各チャンクの目印のような役割を果たします。バウンダリは、リクエストヘッダの content-type に自動的に追加されます。
enctype="multipart/form-data"*属性を持つフォームは、リクエストヘッダーのContent-Type : multipart/form-data; boundary --- WebKit193844043-h (browser generated vaue*)を持つことになります。
渡されるペイロードは次のようなものです。
Content-Type: multipart/form-data; boundary=---WebKitFormBoundary7MA4YWxkTrZu0gW
-----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=”file”; filename=”captcha”
Content-Type:
-----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=”action”
submit
-----WebKitFormBoundary7MA4YWxkTrZu0gW--
ウェブサービス側では、@Consumes("multipart/form-data")フォームで消費されます。
chrome postmanを使用してWebサービスをテストする場合、添付ファイルを送信するには、フォームデータオプション(ラジオボタン)とドロップダウンボックスのファイルメニューをチェックする必要がありますのでご注意ください。コンテントタイプにmultipart/form-dataを明示的に指定するとエラーになります。バウンダリが不足しているため、postmanがサーバにcontent-typeを指定してcurlリクエストする際に、バウンダリを付加することで上書きされ、正常に動作します。
RFC1341 sec7.2 The Multipart Content-Type]1を参照してください。