Content-Disposition
使い方
通常の HTTP レスポンスにおいて、Content-Disposition ヘッダーはブラウザがコンテンツをユーザーにどう提示するかを制御します。値を inline に設定すると、ブラウザはコンテンツを直接描画します。値を attachment に設定すると、代わりにダウンロードのダイアログが表示されます。
このヘッダーは multipart/form-data のレスポンスやフォーム送信でも役割を果たします。マルチパートボディの各パートは独自の Content-Disposition フィールドを持ち、フォームのフィールド名と、アップロードされたファイルの任意のファイル名を示します。パートの境界は Content-Type ヘッダーで定義されます。
inline
inline ディレクティブは、ページ内でコンテンツを直接表示するようブラウザに指示します。Content-Disposition がない場合、これがほとんどのレスポンスにおける既定の挙動です。
attachment
attachment ディレクティブはダウンロードのプロンプトを引き起こします。ブラウザはコンテンツをビューポートに描画するのではなく、「名前を付けて保存」のダイアログを表示します。
filename
filename パラメーターは、ダウンロードされるファイルの既定のファイル名を提案します。値は二重引用符で囲み、ASCII のエンコード規則に従います。
Content-Disposition: attachment; filename="report.pdf"
filename*
filename* パラメーターは、ASCII の範囲を超える文字エンコーディングへの対応を加えて filename を拡張します。filename と filename* の両方が存在する場合、filename* が優先されます。これは ASCII 以外の文字を含むファイル名に役立ちます。
Content-Disposition: attachment; filename="document.pdf"; filename*=UTF-8''d%C3%B6cument.pdf
form-data
form-data ディレクティブはマルチパートのボディパートに現れ、そのコンテンツがフォーム送信に属することを示します。
name
name パラメーターはマルチパートのボディパート内で必須であり、そのパートが対応するフォームのフィールドを示します。
例
CSV ファイルのダウンロードで応答するサーバーは attachment を設定し、推奨されるファイル名を提供します。ブラウザは「export.csv」があらかじめ入力された保存ダイアログを開きます。
Content-Disposition: attachment; filename="export.csv"
PDF をブラウザで直接表示するサーバーは inline を使います。ブラウザはファイルをダウンロードするのではなく、組み込みのビューアーで PDF を描画します。
Content-Disposition: inline
マルチパートのフォーム送信では、各パートが独自の Content-Disposition フィールドを運びます。name パラメーターがパートを対応するフォームのフィールドに対応付け、filename がアップロードされたファイルの元の名前を示します。
Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
トラブルシューティング
Content-Disposition に関するダウンロードや表示の問題は、たいていディレクティブの値の誤りか、ファイル名のエンコードの間違いに起因します。
ファイルが誤ったファイル名でダウンロードされる。ブラウザは filename パラメーターを既定の保存名として使います。filename の値がないか形式が不正だと、ブラウザは URL のパスや汎用的な名前にフォールバックします。値を二重引用符で囲んでください。filename=“report.pdf” のようにします。curl -I https://example.re/file でヘッダーを確認し、レスポンスの filename パラメーターを調べてください。
ファイル名の非 ASCII 文字が壊れる、または文字化けする。filename パラメーターは ASCII 文字しかサポートしません。アクセント付きの文字、CJK 文字、その他の非 ASCII テキストを含む名前には、エンコードの構文を使って filename* パラメーターを追加してください。filename*=UTF-8”d%C3%B6cument.pdf のようにします。ブラウザ間の互換性を最大化するため、filename(ASCII のフォールバック)と filename*(エンコードされた版)の両方を含めてください。
ブラウザが attachment を無視してコンテンツをインライン表示する。一部のブラウザは、PDF や画像のようにネイティブに描画できるコンテンツタイプについて attachment を上書きします。Content-Type ヘッダーがこの挙動に影響します。attachment と併せて Content-Type: application/octet-stream を設定すると、どのファイル形式でもダウンロードが強制されます。ブラウザの拡張機能や組み込みのビューアー(PDF.js)もこのディレクティブを上書きすることがあります。
ダウンロードを期待したのにインライン表示になる。Content-Disposition ヘッダーがない場合、ほとんどのコンテンツタイプで既定は inline になります。ダウンロードを引き起こすには、サーバーが明示的に attachment を送る必要があります。nginx では該当する location ブロックに add_header Content-Disposition “attachment”; を追加します。Apache では
filename と filename* の優先順位。両方のパラメーターが存在する場合、現代のすべてのブラウザで filename* が優先されます。filename* をサポートしない古いクライアントは filename にフォールバックします。常に両方のパラメーターを含めてください。filename* の値では、特殊文字にパーセントエンコーディングを使う必要があります。filename*=UTF-8”na%C3%AFve.txt のようにします。
フレームワーク固有のダウンロードレスポンスのヘルパー。ほとんどの Web フレームワークは、ダウンロード用のヘッダーを設定する組み込みのメソッドを提供しています。Django は as_attachment パラメーター付きの FileResponse を使います。Express は res.download() を使います。Flask は as_attachment=True 付きの send_file() を使います。Rails は disposition オプション付きの send_data や send_file を使います。これらのメソッドはファイル名のエンコードとヘッダーの整形を処理するため、手作業による誤りの可能性が減ります。