在 JavaScript 中進行 Base64 編碼/解碼:btoa()、atob() 與 Unicode
JavaScript 中的 Base64 編碼與解碼
JavaScript 提供了多種內建方式來編碼和解碼 Base64 字串。無論您是開發瀏覽器應用程式還是 Node.js 伺服器,了解如何處理 Base64 對於在 JSON、HTML 和 URL 等文字格式中處理二進位資料至關重要。
在瀏覽器中使用 btoa() 和 atob()
瀏覽器 JavaScript 中用於 Base64 的兩個核心函式是 btoa() 和 atob()。這些函式名稱遵循較早的命名慣例——btoa 代表「binary to ASCII」(二進位轉 ASCII),atob 代表「ASCII to binary」(ASCII 轉二進位)。它們已在所有主流瀏覽器中獲得數十年的支援。
使用 btoa() 編碼
const originalString = 'Hello, world!';
const encoded = btoa(originalString);
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==
使用 atob() 解碼
const base64String = 'SGVsbG8sIHdvcmxkIQ==';
const decoded = atob(base64String);
console.log(decoded);
// Output: Hello, world!
這兩個函式僅適用於僅包含 Latin-1 字元(每個字元由單一位元組表示)的字串。這是接下來要討論的一個重要限制。
處理 Unicode 和非 ASCII 字元
一個常見的陷阱:當傳入包含 Latin-1 範圍外字元(例如表情符號、中文字元或重音字母)的字串時,btoa() 會拋出錯誤。
btoa('Hello 你好');
// Error: The string to be encoded contains characters outside of the Latin-1 range.
要編碼 Unicode 字串,您需要先將字串轉換為位元組,然後再對這些位元組進行編碼。現代的做法是使用 TextEncoder 和 TextDecoder 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);
}
// Usage
const encoded = unicodeToBase64('Hello 你好 🚀');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=
const decoded = base64ToUnicode(encoded);
console.log(decoded);
// Output: Hello 你好 🚀
較舊的技巧是使用 encodeURIComponent 和 decodeURIComponent,但 TextEncoder/TextDecoder 方式更加穩健,是推薦的現代解決方案。
編碼二進位資料(ArrayBuffer)
在使用來自 fetch 或 FileReader 等 API 的檔案、圖片或原始二進位資料時,您通常會取得 ArrayBuffer 或 Uint8Array。以下是將其轉換為 Base64 的方法:
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binaryString = '';
for (let i = 0; i < bytes.length; i++) {
binaryString += String.fromCharCode(bytes[i]);
}
return btoa(binaryString);
}
function base64ToArrayBuffer(base64) {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
在瀏覽器中將檔案轉換為 Base64
以下是一個使用 FileReader 將使用者選取的檔案轉換為 Base64 Data URL 的完整範例:
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error('Failed to read file'));
reader.readAsDataURL(file);
});
}
// Usage with a file input
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
const file = e.target.files[0];
try {
const dataUrl = await fileToBase64(file);
console.log(dataUrl); // data:image/png;base64,iVBORw0KGgo...
} catch (err) {
console.error('Conversion failed:', err);
}
});
在 Node.js 中使用 Base64
Node.js 提供了用於 Base64 操作的 Buffer 類別,比瀏覽器的 btoa/atob 更加靈活。Buffer 類別自動處理編碼和解碼,包括 Unicode,並支援多種編碼格式。
基本編碼與解碼
// Encode a string to Base64
const encoded = Buffer.from('Hello, world!').toString('base64');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==
// Decode a Base64 string back to text
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
Node.js 中的 Unicode 支援
與瀏覽器中的 btoa() 不同,Node.js 的 Buffer 能無縫處理 Unicode:
const encoded = Buffer.from('Hello 你好 🚀').toString('base64');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello 你好 🚀
讀取檔案並編碼為 Base64
const fs = require('fs');
// Read a file and encode it to Base64
const buffer = fs.readFileSync('image.png');
const base64 = buffer.toString('base64');
const dataUrl = `data:image/png;base64,${base64}`;
Node.js 中的 Base64url 編碼
Node.js 15.7.0 以上版本支援原生的 Base64url 編碼,它將 + 替換為 -、/ 替換為 _,並省略填充字元:
const encoded = Buffer.from('Hello, world!').toString('base64url');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ (no padding)
const decoded = Buffer.from(encoded, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
效能考量
對於大型資料,反覆進行 Base64 操作可能會很慢。以下是一些提示:
- 對於 Unicode 字串,使用
TextEncoder/TextDecoder而非手動轉換 - 在 Node.js 中,
Buffer.from()經過高度最佳化——優先使用它而非自行實作 - 除非必要,避免將大型檔案轉換為 Base64(考慮使用串流)
- 對於大型資料集,考慮在瀏覽器中使用
Blob和FileReader以避免阻塞主執行緒
線上試用 Base64 編碼
使用我們的免費線上 Base64 編碼器和解碼器,直接在瀏覽器中嘗試編碼與解碼。無需編寫程式碼——只需貼上文字或上傳檔案,即可立即獲得 Base64 結果。