百分号编码

**百分號編碼**（英語：Percent-encoding），又稱：**URL 編碼**（URL encoding）是特定上下文的統一資源定位符 （URL）的編碼機制，實際上也適用於統一資源標誌符（URI）的編碼。也用於為 _application/x-www-form-urlencoded_ MIME 準備資料，因為它用於通過 HTTP 的請求操作（request）提交 HTML 表單資料。

## URI 的百分號編碼

### URI 的字元類型

URI 所允許的字元分作**保留**與**未保留**。**保留**字元是那些具有特殊含義的字元，例如：斜線字元用於 URL（或 URI）不同部分的分界符；**未保留**字元沒有這些特殊含義。百分號編碼把保留字元表示為特殊字元序列。上述情形隨 URI 與 URI 的不同版本規格會有輕微的變化。

URI 中的其它字元必須用百分號編碼。

### 對保留字元的百分號編碼

如果一個保留字元在特定上下文中具有特殊含義 (稱作 "reserved purpose") , 且 URI 中必須使用該字元用於其它目的，那麼該字元必須百分號編碼。百分號編碼一個保留字元，首先需要把該字元的 ASCII 的值表示為兩個 16 進位的數字，然後在其前面放置跳脫字元 ("`%`")，置入 URI 中的相應位置。(對於非 ASCII 字元，需要轉換為 UTF-8 位元組序，然後每個位元組按照上述方式表示.)

例如，"`/`", 如果用作 URI 的路徑成份的分界符，則是具有特殊含義的保留字元。如果該字元需要出現在 URI 一個路徑成分的**內部**, 則三字元序列 "`%2F`"或"`%2f`"就用於代替原本的"`/`" 出現在該 URI 路徑成分的內部.

在特定上下文中沒有特殊含義的保留字元也可以被百分號編碼，在語意上與不百分號編碼的該字元沒有差別.

在 URI 的 "查詢" 成分 (? 字元後的部分) 中，例如 "`/`" 仍然是保留字元但是沒有特殊含義，除非一個特定的 URI 有其它規定。該 `/` 字元在沒有特殊含義時不需要百分號編碼.

如果保留字元具有特殊含義，那麼該保留字元用百分號編碼的 URI 與該保留字元僅用其自身表示的 URI 具有不同的語意。

### 對未保留字元的百分號編碼

未保留字元不需要百分號編碼.

兩個 URI 的差別如果僅在於_未保留字元_是用百分號編碼還是用字元自身表示，那麼這兩個 URI 具有等價的語意。但 URI 處理器實際上並不總是把二者視作等價。例如，URI 的消費者不應該把 "`%41`"與"`A`", "`%7E`"與"`~`" 視作不同，但是某些 URI 的消費者就是這麼做了。為了最大的互操作性，URI 的製造者不應該對_未保留字元_進行百分號編碼。

### 對百分號字元的百分號編碼

由於百分號字元 ("%") 表示百分號編碼位元組流的存在，因此百分號字元應該被編碼為 3 個位元組的序列："%25"，用於 URI 內部。

### 對任意資料的百分號編碼

大多數 URI 涉及表示任意資料，例如 IP 位址或檔案系統路徑作為 URI 的成分。

#### 二進資料

1994 年發布的 RFC 1738 規定， URI 中的二進位資料應該表示為 8 位元組的序列，然後對每個 8 位元組按照上述方式百分號編碼。例如，位元組值 0F (十六進位) 應表示為 "`%0F`", 位元組值 41 (十六進位) 應表示為"`A`"或"`%41`". 優先使用未保留字元來表示這些位元組值，因為這使得 URL 更短.

#### 字元資料

二進資料的百分號編碼過程已經被外推到字元資料，甚至到不適合或未被完全規範的地步。在 WWW 初創階段，僅僅處理 ASCII 字元是否編碼問題，還沒有什麼問題。但隨後發展到對非 ASCII 字元如何在 URI 中編碼，缺少標準規範的情況下導致了歧義性的解釋 URI 的錯誤。

例如， 基於 RFC 1738 與 RFC 2396 的協定規定，字元資料先要根據某種字元編碼轉換為位元組流，然後再表示為 URI。如果 URI 不提供是何種字元編碼的提示資訊，那麼這個 URI 難以可靠的解析。

### 當前標準

2005 年 1 月發布的 RFC 3986，建議所有新的 URI 必須對未保留字元不加以百分號編碼；其它字元建議先轉換為 UTF-8 位元組序列，然後對其位元組值使用百分號編碼。此前的 URI 不受此標準的影響。

### 非標準的實現

有一些不符合標準的把 Unicode 字元在 URI 中表示為: `%u_xxxx_`, 其中 _xxxx_ 是用 4 個十六進位數字表示的 Unicode 的碼位值。任何 RFC 都沒有這樣的字元表示方法，並且已經被 W3C 拒絕 （頁面存檔備份，存於網際網路檔案館）。第三版的 ECMA-262 仍然包含函式 `escape(string)` 使用這種語法，但也有函式 `encodeURI(uri)` 轉換字元到 UTF-8 位元組序列並用百分號編碼每個位元組。

## application/x-www-form-urlencoded 類型

當 HTML 表單中的資料被提交時，表單的域名與值被編碼並通過 HTTP 的 GET 或者 POST 方法甚至更古遠的 email 把請求傳送給伺服器。這裡的編碼方法採用了一個非常早期的通用的 URI 百分號編碼方法，並且有很多小的修改如換行規格化以及把空格符的編碼 "`%20`"替換為"`+`" 。按這套方法編碼的資料的 MIME 類型是 `application/x-www-form-urlencoded`，當前仍用於（雖然非常過時了）HTML 與 XForms 規範中。此外，CGI 規範包括了 web 伺服器如何解碼這類資料、利用這類資料的內容。

如果傳送的是 HTTP GET 請求，`application/x-www-form-urlencoded` 資料包含在所請求 URI 的查詢成分中。如果傳送的是 HTTP POST 請求或通過 email，資料被放置在訊息體中，媒體類型的名字被包含在訊息的 Content-Type 頭內部。

## 參見

* Quoted-printable

## 參考文獻

## 外部連結

* RFC 3986 / STD 66 (plus errata （頁面存檔備份，存於網際網路檔案館）), the current generic URI syntax specification.
* RFC 2396 (obsolete, plus errata （頁面存檔備份，存於網際網路檔案館）) and RFC 2732 (plus errata （頁面存檔備份，存於網際網路檔案館）) together comprised the previous version of the generic URI syntax specification.
* RFC 1738 (mostly obsolete) and RFC 1808 (obsolete), which define URLs.
* RFC 1630 (obsolete), the first generic URI syntax specification.
* W3C Guidelines on Naming and Addressing: URIs, URLs, ... （頁面存檔備份，存於網際網路檔案館）
* W3C explanation of UTF-8 in URIs （頁面存檔備份，存於網際網路檔案館）
* W3C HTML form content types （頁面存檔備份，存於網際網路檔案館）
* 在線 URL 解碼工具
* 在線 URL 編碼器