HTTPでは、POST dataにはapplication/x-www-form-urlencoded
とmultipart/form-data
の2つの方法があります。私は、multipart/form-data
が使用されている場合に限り、ほとんどのブラウザがファイルをアップロードできることを理解しています。 APIコンテキストでエンコーディングタイプの1つを使用する場合(ブラウザは関係ありません)、追加のガイダンスはありますか?これは例えばかもしれないに基づいている:
私は基本的に、これまでのところ、さまざまなコンテンツタイプの使用に関するWeb上の正式なガイダンスを見つけませんでした。
TL; DR
概要;バイナリ(英数字以外)のデータ(またはかなり大きいサイズのペイロード)を送信する場合は、multipart/form-data
を使用してください。それ以外の場合はapplication/x-www-form-urlencoded
を使用してください。
ここで言及しているMIMEタイプは、HTTP用の2つのContent-Type
ヘッダーです。POSTは、ユーザーエージェント(ブラウザ)がサポートしている必要があります。これら両方のタイプの要求の目的は、名前と値のペアのリストをサーバーに送信することです。送信されるデータの種類と量に応じて、いずれかの方法が他の方法よりも効率的になります。その理由を理解するために、あなたはそれぞれがカバーの下で何をしているのかを見なければなりません。
application/x-www-form-urlencoded
の場合、サーバーに送信されるHTTPメッセージの本文は基本的に1つの巨大なクエリ文字列です。名前と値のペアはアンパサンド(&
)で区切られ、名前は値と等号(=
)で区切られます。この例は次のようになります。
MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
specification によると:
[予約および]英数字以外の文字は、パーセント記号とその文字のASCIIコードを表す2桁の16進数である `%HH 'に置き換えられます。
つまり、いずれかの値に含まれる英数字以外のバイトごとに、それを表すのに3バイトかかります。大きなバイナリファイルの場合、ペイロードを3倍にすることは非常に非効率的です。
それがmultipart/form-data
が登場するところです。名前/値のペアを送信するこの方法では、各ペアはMIMEメッセージの「一部」として表現されます(他の回答で説明されているように)。部分は特定の文字列境界で区切られています(この境界文字列がどの "値"ペイロードにも含まれないように特別に選択されています)。それぞれの部分にはContent-Type
、特にContent-Disposition
のような独自のMIMEヘッダーのセットがあり、それぞれの部分に「名前」を付けることができます。各名前/値ペアの値部分は、MIMEメッセージの各部分のペイロードです。 MIME仕様は、ペイロード値を表すときにより多くのオプションを提供します。帯域幅を節約するために、バイナリデータのより効率的なエンコードを選択できます(例:base 64またはrawバイナリ)。
なぜmultipart/form-data
をずっと使わないのですか?短い英数字値(ほとんどのWebフォームと同様)では、すべてのMIMEヘッダーを追加することによるオーバーヘッドが、より効率的なバイナリエンコードによる節約よりも大幅に優先されます。
READ ATここから最初のパラを失います!
私はこれが3年遅すぎることを知っていますが、Mattの(受け入れられた)答えは不完全であり、最終的にあなたをトラブルに巻き込むでしょう。ここで重要なのは、multipart/form-data
を使用することを選択した場合、サーバーが最終的に受信するファイルデータにnotが表示される必要があることです。
これはapplication/x-www-form-urlencoded
の問題ではありません。境界がないためです。 x-www-form-urlencoded
は、1つの任意のバイトを3つの7BIT
バイトに変換するという簡単な手段により、常にバイナリデータを処理することもできます。効率的ではありませんが、機能します(ファイル名やバイナリデータを送信できないことに関するコメントが間違っていることに注意してください。別のキー/値のペアとして送信するだけです)。
multipart/form-data
の問題は、境界区切り記号がファイルデータに存在してはならないことです( RFC 2388 を参照してください。セクション5.2には、適切な集約MIMEタイプがこの問題を回避します)。
したがって、一見、multipart/form-data
は、anyファイルのアップロード、バイナリなどでまったく価値がありません。境界を正しく選択しないと、プレーンテキストまたは生のバイナリを送信しているかどうかにかかわらず、最終的にに問題が発生します。サーバーは間違った境界を見つけます。ファイルを切り捨てるか、POSTが失敗します。
重要なのは、選択した境界文字がエンコードされた出力に表示されないように、エンコードと境界を選択することです。 1つの簡単な解決策は、base64
を使用することです(donotrawバイナリを使用します)。 base64 では、任意の3バイトが4つの7ビット文字にエンコードされます。出力文字セットは[A-Za-z0-9+/=]
(つまり、英数字、 '+'、 '/'または '=')です。 =
は特殊なケースであり、エンコードされた出力の最後に、シングル=
またはダブル==
としてのみ表示されます。ここで、base64
出力に表示できない7ビットASCII文字列として境界を選択します。ネット上で見られる多くの選択肢はこのテストに失敗します-MDN形式 docs は、たとえば、バイナリデータを送信するときに境界として「blob」を使用します-良くありません。ただし、「!blob!」のようなものbase64
出力には表示されません。
私は、HTTPがマルチパートのPOSTやx-www-form-urlencodedに限定されるとは思わない。 Content-Type Header は、HTTP POSTメソッドと直交しています(自分に合ったMIMEタイプを入力できます)。これは、典型的なHTML表現ベースのWebアプリケーションの場合も同様です(例:jsonペイロードは、ajaxリクエストのペイロードを送信するために非常に一般的になりました)。
Restful API over HTTPに関して、私が連絡を取った最も人気のあるコンテンツタイプはapplication/xmlとapplication/jsonです。
バイナリデータを自分の資産/リソースとして表現しようと思います。それは別の呼び出しを追加しますが、より良いものを切り離します。サンプル画像:
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... multipart data
201 Created
Location: http://imageserver.org/../foo.jpg
後のリソースでは、バイナリリソースをリンクとしてインライン化することができます。
<main-resource>
...
<link href="http://imageserver.org/../foo.jpg"/>
</main-resource>
私はマヌエルが言ったことの多くに同意します。実際、彼のコメントはこのURLを参照しています...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... どの州:
コンテンツタイプ "application/x-www-form-urlencoded"は、ASCII以外の文字を含む大量のバイナリデータまたはテキストを送信するには非効率的です。コンテンツタイプ "multipart/form-data"は、ファイル、非ASCIIデータ、およびバイナリデータを含むフォームを送信するために使用する必要があります。
しかし、私にとっては、ツール/フレームワークのサポートになります。
あなたがあなたのユーザについて、そして彼らがあなたのAPIをどのように利用するかについての明確な考えを得たなら、それはあなたが決めるのを助けるでしょう。あなたがあなたのAPIユーザにとってファイルのアップロードを困難にするならば、彼らは動かないでしょう、あなたはそれらをサポートすることに多くの時間を費やすでしょう。
これに次ぐものはあなたがあなたのAPIを書くためにあなたが持っているツールサポートとあなたが他のものの上に1つのアップロードメカニズムに対応するのがどれくらい簡単であるかであろう。
私はプリントショップのプロジェクトに取り組んでいますが、HTML5のcanvas
要素から取得した画像をサーバーにアップロードすることで問題が発生しました。私は少なくとも1時間奮闘していました、そして、私はそれを私のサーバーに正しく保存することができませんでした。
私のjQuery ajax呼び出しのcontentType
オプションをapplication/x-www-form-urlencoded
に設定すると、すべてが正しく行われ、base64エンコードデータは正しく解釈され、画像として正常に保存されました。
多分それは誰かを助けます!
Content-Type = x-www-urlencode-formを使用する必要がある場合は、FormDataCollectionをパラメータとして使用しないでください。asp.net Core 2+のFormDataCollectionには、フォーマッタに必要なデフォルトのコンストラクタはありません。代わりにIFormCollectionを使用してください。
public IActionResult Search([FromForm]IFormCollection type)
{
return Ok();
}