🔐
← 返回教學列表

在 JavaScript 中進行 Base64 編碼/解碼:btoa()、atob() 與 Unicode

· 標籤: javascript, base64, btoa, atob, nodejs, encoding, web-development

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 字串,您需要先將字串轉換為位元組,然後再對這些位元組進行編碼。現代的做法是使用 TextEncoderTextDecoder 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 你好 🚀

較舊的技巧是使用 encodeURIComponentdecodeURIComponent,但 TextEncoder/TextDecoder 方式更加穩健,是推薦的現代解決方案。

編碼二進位資料(ArrayBuffer)

在使用來自 fetchFileReader 等 API 的檔案、圖片或原始二進位資料時,您通常會取得 ArrayBufferUint8Array。以下是將其轉換為 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(考慮使用串流)
  • 對於大型資料集,考慮在瀏覽器中使用 BlobFileReader 以避免阻塞主執行緒

線上試用 Base64 編碼

使用我們的免費線上 Base64 編碼器和解碼器,直接在瀏覽器中嘗試編碼與解碼。無需編寫程式碼——只需貼上文字或上傳檔案,即可立即獲得 Base64 結果。