私は、Content-Length
HTTPヘッダーを設定することと、チャンクエンコーディングを使用して[おそらく]サーバーから大きなファイルを返すことの長所と短所を比較検討しています。永続的な接続を使用してHTTP 1.1仕様に準拠するには、どちらか一方が必要です。 Content-Length
ヘッダーの利点は次のとおりです。
欠点は、オブジェクトを返す前にサイズを計算する必要があることです。これは、常に実用的であるとは限らず、サーバー/データベースの使用率を増加させる可能性があります。チャンクエンコーディングの欠点は、各チャンクとダウンロードプログレスバーの前にチャンクサイズを追加することによる小さなオーバーヘッドです。何かご意見は?私が考えていなかったかもしれない他のHTTPに関する考慮事項
確かにContent-Lengthを使用してください。これによるサーバーの使用率はほとんどなくなり、ユーザーにとってのメリットは大きくなります。
動的コンテンツの場合、圧縮応答サポート(gzip)を追加することも非常に簡単です。これには出力バッファリングが必要であり、これによりコンテンツの長さが得られます。 (ファイルのダウンロードや既に圧縮されたコンテンツ(サウンド、画像)では実用的ではありません)。
部分的なコンテンツ/バイト範囲の提供、つまりダウンロードを再開する機能のサポートを追加することも検討してください。 バイト範囲の例についてはこちらを参照 (例はPHPにありますが、任意の言語に適用できます)。部分的なコンテンツを提供する場合はContent-Lengthが必要です。
もちろん、これらは特効薬ではありません。ストリーミングメディアの場合、出力バッファリングや応答サイズを使用しても意味がありません。大きなファイルの場合、出力バッファリングは意味がありませんが、Content-Lengthとバイトサービングは非常に意味があります(失敗したダウンロードの再開が可能です)。
個人的に、私はそれを知っているときはいつでもContent-Lengthを提供します。ファイルのダウンロードの場合、ファイルサイズの確認はリソースの点では重要ではありません。結果:ユーザーには確定的な進行状況バーがあります(gzipのおかげで動的ページのダウンロードが速くなります)。
コンテンツの長さが事前にわかっている場合は、チャンクで送信するよりも確実に優先します。ローカルディスクファイルシステムまたはデータベースに静的ファイルの手段がある場合、自尊心のあるプログラミング言語とRDBMSは、コンテンツの長さを事前に取得する方法を提供します。あなたはそれを利用するべきです。
一方、コンテンツの長さが事前に本当に予測不可能である場合(たとえば、いくつかのファイルをまとめてZipして1つとして送信する場合)、サーバーのメモリにバッファリングしたり、ローカルディスクに書き込んだりするよりも、チャンクで送信する方が速い場合があります。最初にファイルシステム。ただし、ダウンロードの進行状況が不明であるため、これは実際にユーザーエクスペリエンスに悪影響を及ぼします。せっかちな人はダウンロードを中止して先に進むかもしれません。
コンテンツの長さを事前に知ることのもう1つの利点は、ダウンロードを再開できることです。あなたの投稿履歴で、主なプログラミング言語はJavaであることがわかりました。あなたは here より技術的な背景情報とJavaそれを行うサーブレットの例を含む記事を見つけることができます。
Content-Length
Content-Length
ヘッダーは、リクエスト/レスポンス本文のバイト長を決定します。 Content-Length
ヘッダーを指定しなかった場合、HTTPサーバーは暗黙的にTransfer-Encoding: chunked
ヘッダーを追加します。 Content-Length
ヘッダーとTransfer-Encoding
ヘッダーを一緒に使用しないでください。受信者はボディの長さがわからないため、ダウンロード完了時間を予測できません。 Content-Length
ヘッダーを追加する場合は、本文全体がバイト単位で一致することを確認してください。正しくない場合、レシーバーの動作は未定義です。
Content-Length
ヘッダーはストリーミングを許可しませんが、部分的なコンテンツサービスをサポートする必要がある大きなバイナリファイルに役立ちます。これは基本的に、再開可能なダウンロード、一時停止したダウンロード、部分的なダウンロード、マルチホームダウンロードを意味します。これには、Range
という追加のヘッダーを使用する必要があります。この手法は Byte serve と呼ばれます。
Transfer-Encoding
Transfer-Encoding: chunked
の使用により、単一の要求または応答内でのストリーミングが可能になります。つまり、データはチャンク形式で送信され、コンテンツの表現には影響しません。
正式には、HTTPクライアントは、クライアントが受け入れようとしている転送エンコーディングの種類を指定するTE
ヘッダーフィールドを含むリクエストを送信することを意図しています。これは常に送信されるわけではありませんが、ほとんどのサーバーはクライアントがchunked
エンコーディングを処理できると想定しています。
chunked
転送エンコーディングは、永続的なTCP接続をより適切に使用します。HTTP1.1はデフォルトでtrueであると想定しています。
Content-Encoding
チャンクされたデータまたはチャンクされていないデータを圧縮することもできます。これは実際にはContent-Encoding
ヘッダーを介して行われます。
Content-Length
は、Content-Encoding
の後の本文の長さに等しいことに注意してください。つまり、応答をgzip圧縮した場合、圧縮後に長さの計算が行われます。長さを計算する場合は、ボディ全体をメモリにロードできる必要があります(他にその情報がない場合)。
チャンクエンコーディングを使用してストリーミングする場合、圧縮アルゴリズムはオンライン処理もサポートする必要があります。ありがたいことに、gzipはストリーム圧縮をサポートしています。コンテンツは最初に圧縮され、次にチャンクに切り分けられると思います。このようにして、チャンクが受信され、解凍されて実際のコンテンツが取得されます。逆の場合は、圧縮されたストリームを取得し、解凍するとチャンクが得られます。これは意味がありません。
一般的な圧縮ストリーム応答には、次のヘッダーがあります。
Content-Type: text/html
Content-Encoding: gzip
Transfer-Encoding: chunked
意味的には、Content-Encoding
の使用は「エンドツーエンド」のエンコーディングスキームを示します。つまり、最終的なクライアントまたは最終的なサーバーのみがコンテンツをデコードすることになります。真ん中のプロキシはコンテンツをデコードすることを想定していません。
途中のプロキシにコンテンツのデコードを許可する場合、実際に使用する正しいヘッダーはTransfer-Encoding
ヘッダーです。 HTTPリクエストがTE: gzip chunked
ヘッダーを所有していた場合、Transfer-Encoding: gzip chunked
で応答することは正当です。
ただし、これがサポートされることはほとんどありません。したがって、現時点では、圧縮にはContent-Encoding
のみを使用する必要があります。