繁體中文

開發者工具 · URL 編碼器和解碼器

檔案下載連結中的空格:為什麼 %20、+ 和原始空格不同

· 為什麼它很重要

url 編碼 http 開發人員工作流程

下載檔案名稱中空格的三種編碼方法比較
原始 ToolAcre 向量圖

名為“Q3 報告(最終).pdf”的檔案可以通過三種不同的方式連結,但只有一種是可靠正確的。這篇文章解釋了為什麼檔案名會破壞下載連結以及如何對其進行編碼以便每個客戶都同意。

下載對某些使用者失敗但對其他使用者有效 - 檔案名稱帶有空格和加號

像「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 報告(最終)+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 和百分比編碼。瀏覽器解釋這些標頭來決定保存檔案名稱。相同的檔案名稱使用不同的方案進行兩次編碼。

兩個編碼層會產生轉碼錯誤的機會。如果伺服器和用戶端不一致,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 儲存體有不同的字元規則。在 S3 上工作的檔案名稱在 Azure 上可能會失敗。架構師必須檢查提供者檔案並使用真實的非 ASCII 檔案名稱進行測試。

重點:對段進行編碼,而不是 URL — URL 編碼器和解碼器的單值模式如何產生路徑安全的檔案名稱

重點:對段進行編碼,而不是 URL — URL 編碼器和解碼器單值模式產生路徑安全的檔案名稱。該工具接受原始檔案名稱並產生百分比編碼的段落。這可以防止雙重編碼和混合上下文。使用單值模式可以避免平衡路徑、查詢和片段編碼規則。產生的段可以安全地插入到 URL 中。

最佳實務對進入 URL 建構的檔案名稱進行編碼。不要假設瀏覽器可以解決編碼問題。使用目標使用者使用的實際 HTTP 用戶端進行測試:curl、wget、Python、Java httplib 和瀏覽器取得 API。驗證檔案名稱能否在整個系統中往返。 URL編碼器和解碼器是確保正確性的起點。