開発者ツール · URL エンコーダーとデコーダー
ファイル ダウンロード リンク内のスペース: %20、+、および生のスペースが同じではない理由
· なぜそれが重要なのか
URLエンコーディング http 開発者ワークフロー
「Q3 レポート (最終).pdf」というファイルは 3 つの異なる方法でリンクできますが、確実に正しいのは 1 つだけです。この投稿では、ファイル名によってダウンロード リンクが壊れる理由と、すべてのクライアントが同意するようにファイル名をエンコードする方法について説明します。
一部のユーザーでは失敗し、他のユーザーでは機能するダウンロード - スペースとプラス記号を含むファイル名
「Q3 report.pdf」のようなファイルは、ローカルに保存すると正常に動作しますが、一部のユーザーではダウンロード リンク経由で失敗しますが、問題なく成功するユーザーもいます。 RFC 3986 仕様に従って、URL では生のスペースは無効です。ブラウザはアドレス バーでこれらを許容しますが、HTTP クライアントはそれらを厳密に拒否します。 %20、プラス記号、および生のスペースを理解することは、信頼性の高い配布のために不可欠です。エンコード方式の違いは、世界中のさまざまなプラットフォーム、さまざまな自動化ツール、HTTP クライアント実装におけるダウンロードの成功率に直接影響します。開発者は、ダウンロード システムを構築する際に、この違いを理解する必要があります。エンコーディングの選択とシステムの互換性にはコンテキストが重要です。
開発者は、ダウンロード リンクを作成するときに、生のスペース、%20、またはプラス記号のいずれかを選択する必要があります。 curl、wget、および Python を使用してテストすると、どのクライアントが RFC 準拠を強制しているかが明らかになります。ブラウザのダウンロードはエラー回復により成功しますが、エンコードされていないスペースが発生すると API 統合は失敗します。
URL では未加工のスペースが無効な理由、およびブラウザーはアドレス バー内で生のスペースを許容するが、HTTP クライアントはそれを許容しない理由
URL 内の生のスペースは、プロトコル設計に歴史的なルーツがあります。 URL は、スペースをトークン間の区切り文字として扱うシステムを横断します。 URL 内のスペースは、ターミネータとして誤って解釈される可能性があります。コマンドラインから読み取る HTTP クライアントは最初のスペースで切り捨てられます。この基本的な設計はプロトコルの実装に残り、変更される可能性は低いです。
ブラウザーは、HTTP リクエストを送信する前に %20 にサイレント変換することで生のスペースを許容します。このユーザーフレンドリーな動作により、エンドユーザーがアドレスバーに URL を貼り付けることからプロトコル要件が見えなくなります。自動化システムにはこの回復層がありません。未加工のスペースを含む URL ではスクリプトが失敗します。電子メール クライアントは、そのようなリンクを開くときにエラーが発生します。
%20 とパス セグメント内の + の比較 — パスには適用されないフォーム エンコーディング規則
%20 とプラス記号は、URL エンコード コンテキストにおける基本的な違いを表します。パス セグメントでは、スペースは RFC 3986 に従って %20 としてエンコードする必要があります。プラス記号はパス内のスペース エンコーディングではありません。この規則は、クエリ文字列内のスペース エンコーディングとして機能する HTML フォーム エンコーディングに由来しています。開発者は、パスにフォーム ルールを誤って適用することがよくあります。
プラス記号を許可するフォーム エンコーディング規則は、異なる構造要件を持つパスには適用されません。クエリ文字列では、アンパサンドと等号でパラメータを区切ります。クエリ値のスペースにプラスを使用すると、プラスは区切り文字ではないため、あいまいさが生じません。パスでは、plus には特別な意味はありません。規則を混合すると、壊れたダウンロード リンクが作成されます。
非 ASCII ファイル名 — UTF-8 パーセントエンコーディングおよび生の名前を保存するオブジェクトストレージキー
非 ASCII ファイル名は、URL で安全に送信する前に UTF-8 パーセント エンコーディングが必要です。 「Über report.pdf」のようなファイル名には、ASCII 範囲外の「Ü」(U+00DC)が含まれています。 UTF-8 エンコーディングは、これをバイト C3 9C に変換します。これらのバイトは、URL では %C3%9C としてパーセント エンコードされます。各 UTF-8 バイトは独自のトリプレットを取得し、より長いエンコードされたファイル名が生成されます。
Amazon S3 などのオブジェクト ストレージ サービスでは、非 ASCII ファイル名について興味深いケースが存在します。一部のシステムではキーに生の UTF-8 バイトを使用できますが、他のシステムではパーセント エンコーディングが必要です。エンコード戦略は、ストレージ プロバイダーと URL の使用状況によって異なります。 URL ベースのアクセスには、パーセントエンコードされた UTF-8 が必要です。開発者はストレージ層と URL 生成層を調整する必要があります。
作業例: 'Über Q3 report (final)+notes.pdf' をパスにエンコード - 正確な出力と、+ が %2B になる必要がある理由
作業例: 「Über report (final)+notes.pdf」のエンコードは完全なエンコードを示しています。ファイル名には、スペース、非 ASCII 文字、およびリテラルのプラスが含まれています。 「Ü」の UTF-8 エンコードでは %C3%9C が生成されます。パス エンコードでは、スペースは %20 になります (プラスを使用したフォーム エンコードとは異なります)。リテラルのプラスは %2B になります。括弧は %28 および %29 としてエンコードされます。結果: %C3%9CberQ3%20report%20%28final%29%2Bnotes.pdf。
URL エンコーダーとデコーダーを使用したテストでは、正確な変換が示されています。ファイル名を単一値モードに貼り付けると、パス規則を使用して正しいパーセントエンコードされたセグメントが生成されます。このツールは、ファイル名コンポーネントのみをエンコードする際に、パス区切り文字を保持します。入力と出力を視覚的に比較することで、ルールが明確になり、運用前に検証可能になります。これをフォーム モードと比較して、コンテキストの違いを確認します。
Content-Disposition と filename* パラメーター — ダウンロード プロンプトの別のエンコーディング (完全を期すために言及)
Content-Disposition および filename* パラメーターは、ダウンロード プロンプトの代替エンコード層を表します。サーバーには、ダウンロード ダイアログのファイル名を指定する Content-Disposition ヘッダーが含まれています。 filename パラメーターは RFC 2183 エンコーディングを使用し、filename* はパーセントエンコーディングの RFC 5987 を使用します。ブラウザはこれらのヘッダーを解釈して保存ファイル名を決定します。同じファイル名が異なるスキームで 2 回エンコードされます。
2 つのエンコード層により、トランスコード エラーが発生する可能性があります。サーバーとクライアントの意見が一致しない場合、URL エンコードされたファイル名とヘッダーエンコードされたファイル名は正しくラウンドトリップしない可能性があります。互換性を最大限に高めるために、開発者は %20 および UTF-8 パーセント エンコーディングを使用して URL パス内のファイル名をエンコードし、デコードされたファイル名を使用して Content-Disposition ヘッダーを設定する必要があります。これにより、すべての HTTP クライアントとブラウザが正しく動作することが保証されます。
これでカバーされないもの — 特定のオペレーティング システムで予約されたファイル名とストレージ プロバイダーの癖
特定のオペレーティング システムで予約されたファイル名により、URL エンコードが複雑になります。 Windows では、デバイス用に CON、PRN、AUX などの名前が予約されています。文字通り「CON.pdf」という名前のファイルは NTFS 上に存在できません。 macOS には命名規則と拡張属性ルールがあります。 Linux では大文字と小文字が区別されます。有効な URL エンコードされたファイル名は、特定のシステムのストレージでは有効ではない可能性があります。
ストレージ プロバイダーの特殊性により、クロスプラットフォームの配布が複雑になります。 Amazon S3 は UTF-8 キーを受け入れ、大文字と小文字が区別されます。 Google Cloud Storage も同様に動作しますが、追加の制限があります。 Azure Blob Storage にはさまざまな文字ルールがあります。 S3 で機能するファイル名は、Azure では失敗する可能性があります。アーキテクトはプロバイダーのドキュメントを確認し、実際の非 ASCII ファイル名を使用してテストする必要があります。
要点: URL ではなくセグメントをエンコードする — URL エンコーダーとデコーダーの単一値モードがパスセーフなファイル名を生成する方法
要点: URL ではなくセグメントをエンコードします。URL エンコーダーおよびデコーダーの単一値モードは、パスセーフなファイル名を生成します。このツールは生のファイル名を受け入れ、パーセントでエンコードされたセグメントを生成します。これにより、二重エンコードやコンテキストの混合が防止されます。単一値モードを使用すると、パス、クエリ、およびフラグメントのエンコーディング ルールのバランスをとることが回避されます。生成されたセグメントは URL に安全に挿入できます。
ベスト プラクティスでは、URL 構築に入るファイル名をエンコードします。ブラウザーがエンコードの問題を解決するとは考えないでください。ターゲット ユーザーが使用する実際の HTTP クライアント (curl、wget、Python、Java httplib、およびブラウザー フェッチ API) を使用してテストします。ファイル名がシステム全体を往復しても存続することを確認します。 URL エンコーダとデコーダは、正確性を確保するための出発点です。