Base64 編碼 / 解碼 常見問題
Q: 什麼是 Base64 編碼?它有什麼用途?
A: Base64 是一種二進位轉文字的編碼方案,使用 64 個字元(A-Z、a-z、0-9、+、/)將二進位資料轉換為 ASCII 字串格式。它主要用於透過 HTTP、SMTP 等文字型通訊協定或在 JSON 酬載中傳輸二進位資料。常見應用包括透過 MIME 傳送電子郵件附件、以 Data URL 形式將圖片嵌入 HTML 與 CSS、在 JSON Web Token(JWT)中編碼酬載,以及將二進位資料儲存在文字型資料庫欄位中。
Q: Base64 是加密嗎?它安全嗎?
A: 不是。Base64 是一種編碼方案,而非加密。任何取得 Base64 編碼字串的人都可以立即將其解碼回原始資料,無需任何金鑰、密碼或秘密。它不提供機密性、完整性或身分驗證。可以將其視為用不同格式來表示相同資料的方式——就像將英文翻譯成摩斯密碼一樣。如果您需要保護敏感資料,請先使用適當的加密演算法(例如 AES),然後可選擇性地將加密後的位元組以 Base64 編碼以便傳輸。
Q: 為什麼 Base64 有時會以 = 或 == 符號結尾?
A: = 字元是填充字元。Base64 以 3 個位元組(24 位元)為一組處理輸入資料,每組產生 4 個 Base64 字元。當輸入長度不是 3 位元組的倍數時,編碼會加入填充 = 字元,使輸出長度成為 4 的倍數。剩餘 2 個位元組時加入一個 =,僅剩 1 個位元組時加入兩個 = 字元。例如,"Man"(3 位元組)編碼為 "TWFu"(無填充),但 "Ma"(2 位元組)編碼為 "TWE=","M"(1 位元組)編碼為 "TQ=="。
Q: Base64 會讓資料變大嗎?它會增加多少額外開銷?
A: 會,Base64 編碼會使資料大小增加約 33%。每 3 位元組的二進位輸入會產生 4 位元組的輸出,再加上可選的填充字元。因此,一個 3 MB 的二進位檔案經過 Base64 編碼後大約變成 4 MB。這是為了能夠在純文字通道上傳輸二進位資料而做出的取捨。與其他二進位轉文字編碼相比,Base64 相對高效——例如,十六進位編碼會增加 100% 的開銷。
Q: 標準 Base64 和 Base64url 有什麼區別?
A: 標準 Base64 使用 + 和 / 作為其字元集,並使用 = 作為填充。Base64url(URL 安全 Base64)將 + 替換為 -,將 / 替換為 _,且通常省略填充字元。這使得 Base64url 可以安全地用於 URL、查詢參數和檔案名稱中,無需額外的百分比編碼。Base64url 定義於 RFC 4648,廣泛應用於 JSON Web Token(JWT)、OAuth Token 和 Web API 中。例如,標準 Base64 字串 Pj4+Pz8/Pw== 在 Base64url 中變成 Pj4-Pz8_Pw。
Q: 什麼是 Base64 Data URL?如何在 HTML 和 CSS 中使用它?
A: Data URL 是一種直接將資料嵌入網頁文件的 URI 方案。對於圖片,其格式為 data:image/png;base64,iVBORw0KGgo...。它可以用於取代 HTML <img> 標籤和 CSS background-image 屬性中的檔案 URL。Data URL 消除了載入圖片所需的獨立 HTTP 請求,對於小型資源(通常小於 10 KB)可以提升效能。然而,它會使 HTML/CSS 檔案大小增加約 33%,且瀏覽器無法獨立快取該圖片。
Q: 可以將任何檔案轉換為 Base64 嗎?
A: 可以——任何二進位資料,無論是文字、圖片、音訊、影片、PDF 還是壓縮檔,都可以編碼為 Base64。流程相同:讀取檔案的原始位元組,然後應用 Base64 編碼演算法。當您解碼 Base64 字串時,會得到完全相同的原始位元組。這就是電子郵件附件的運作方式——二進位檔案在透過 SMTP 傳送之前先進行 Base64 編碼,接收端再將其解碼回原始檔案。
Q: 在 JavaScript 中編碼 Base64 時,如何處理 Unicode 字元(例如表情符號或中文字)?
A: 內建的 btoa() 函式僅適用於 Latin-1 字元(單位元組字元)。對於包含表情符號、中文字元或其他多位元組字元的 Unicode 字串,您需要先使用 TextEncoder API 將其轉換為位元組:
function unicodeToBase64(str) {
const bytes = new TextEncoder().encode(str);
const binaryString = String.fromCharCode(...bytes);
return btoa(binaryString);
}
function base64ToUnicode(base64) {
const binaryString = atob(base64);
const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
在 Node.js 中,Buffer 類別原生支援 Unicode:Buffer.from('Hello 你好 🚀').toString('base64') 無需任何特殊處理即可運作。