在 Web 開發中,最常見的三種文字編碼方式各有其設計目的和適用場景。混用或誤用這三種編碼是開發者常見的問題根源。
將字元轉為 %XX 格式,讓任意字元都能安全地出現在 URL 中。RFC 3986 標準。
將任意二進位資料轉為 64 個可列印 ASCII 字元,適合在文字協議中傳輸二進位資料。
將 HTML 特殊字元(< > & " ')轉為實體形式,防止 XSS 攻擊。
| 特性 | URL 編碼 | Base64 | HTML 實體 |
|---|---|---|---|
| 標準規範 | RFC 3986 | RFC 4648 | HTML5 / WHATWG |
| 輸入類型 | 文字字元 | 任意位元組(二進位) | HTML 文字內容 |
| 輸出格式 | %XX 十六進位 | A-Z, a-z, 0-9, +, / | &name; 或 &#XXX; |
| 資料膨脹率 | 非 ASCII 字元 +200% | 固定 +33% | 視字元而定,通常較少 |
| 可逆性 | 是(解碼) | 是(解碼) | 是(HTML parser 解析) |
| 是否加密 | 否 | 否 | 否 |
| 主要用途 | URL query string、路徑 | 二進位資料傳輸、JWT、資料 URI | HTML 頁面內容輸出 |
僅有英文字母(A-Z、a-z)、數字(0-9)及 - _ . ~ 四個符號不需編碼,其他所有字元先轉 UTF-8 再以 %XX 表示。
// 範例
encodeURIComponent('Hello World!') // → "Hello%20World%21"
encodeURIComponent('中文') // → "%E4%B8%AD%E6%96%87"
encodeURIComponent('a=1&b=2') // → "a%3D1%26b%3D2"
encodeURIComponent('price: $9.99') // → "price%3A%20%249.99"
每 3 個位元組(24 位元)轉為 4 個 Base64 字元(每個 6 位元)。不足 3 位元組時補 = padding。
// 標準 Base64
btoa('Hello') // → "SGVsbG8="
btoa('Hello World') // → "SGVsbG8gV29ybGQ="
// 注意:btoa 不支援非 ASCII 字元,需先 UTF-8 編碼
btoa(unescape(encodeURIComponent('中文'))) // → "5Lit5paH"
// URL-safe Base64(替換 + → - 和 / → _)
// 常用於 JWT 的 header 和 payload
| 原始字元 | HTML 實體(名稱) | HTML 實體(數字) | 原因 |
|---|---|---|---|
| & | & | & | 實體起始符號 |
| < | < | < | HTML 標籤起始 |
| > | > | > | HTML 標籤結尾 |
| " | " | " | 屬性值引號 |
| ' | ' | ' | 屬性值單引號 |
| |   | 不換行空格 |
// JavaScript 中的 HTML 實體編碼
function escapeHtml(str) {
return str
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
escapeHtml('')
// → "<script>alert("XSS")</script>"
// 框架通常自動處理(Vue、React 等)
// Vue: {{ userInput }} // 自動 HTML 編碼
// React: {userInput} // 自動 HTML 編碼
在實際 Web 開發中,常常需要同時處理多種編碼。以下是正確的使用順序:
// 場景:在 HTML 頁面中顯示一個含有動態 URL 的連結
// 使用者搜尋關鍵字:台北 & 新竹 美食
const keyword = '台北 & 新竹 美食';
// 步驟 1:URL 編碼用於 URL 參數
const encodedKeyword = encodeURIComponent(keyword);
// → "%E5%8F%B0%E5%8C%97%20%26%20%E6%96%B0%E7%AB%B9%20%E7%BE%8E%E9%A3%9F"
// 步驟 2:HTML 實體編碼用於輸出到 HTML
const safeUrl = `/search?q=${encodedKeyword}`;
const safeHtml = escapeHtml(safeUrl);
// 確保 URL 中的 & 等字元在 HTML href 屬性中安全
// 最終輸出的 HTML
// <a href="/search?q=%E5%8F%B0%E5%8C%97%20%26...">...</a>
| 問題場景 | 應該使用 |
|---|---|
| 我需要把中文放進 URL query string | URL 編碼 encodeURIComponent() |
| 我需要把圖片直接嵌入 HTML | Base64 data URI 格式 |
| 我需要在 HTML 中輸出使用者提供的文字 | HTML 實體 防止 XSS |
| 我需要傳遞 API 認證資訊 | Base64 HTTP Basic Auth |
| 我需要在 JSON 中傳輸二進位檔案 | Base64 序列化二進位 |
| 我的 URL 含有 HTML 輸出 | URL 編碼 + HTML 實體 兩者都要 |
| 我需要讓特殊字元在 URL 分享後可讀 | URL 編碼 標準做法 |
| 我要製作 JWT Token | Base64 URL-safe 變體 |
記憶原則:
URL 編碼 → 讓字元在 URL 中安全傳輸
Base64 → 讓二進位資料在文字環境中傳輸
HTML 實體 → 讓文字在 HTML 中安全顯示