JavaScript Base64 例項:JSON、檔案和位元組陣列

用支援 UTF-8 的 JavaScript 處理 JSON 與本地檔案,避免把任意二進位制誤當成文字。

寫 Base64 程式碼之前先確定輸入是什麼:JavaScript 字串需要選擇字元編碼;檔案本來就是位元組;JSON 物件則需要先序列化。把步驟分開,能避免重複編碼,也方便定位失敗發生在哪一層。

編碼小型 JSON 物件

物件先經過一次 JSON.stringify,再轉為 UTF-8 位元組,最後編碼 Base64。示例保留中文欄位,可以發現只對英文有效的錯誤實現。臨時位元組字串會佔用額外記憶體,因此此寫法面向小型資料。

const value = { message: '你好', count: 3 };
let binary = '';
for (const byte of new TextEncoder().encode(JSON.stringify(value))) {
  binary += String.fromCharCode(byte);
}
const encoded = btoa(binary);
const bytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const json = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
console.log(JSON.parse(json).message); // 你好

Base64 解碼成功不代表 JSON 有效。UTF-8 解碼和 JSON.parse 應分別處理錯誤。已經是 JSON 文本的字串如果再次序列化,會增加引號和跳脫字元,從而改變資料。

檔案按原始位元組讀取

瀏覽器中的 File 可以通過 arrayBuffer() 讀取。圖片、壓縮包或加密檔案不能通過 file.text() 再編碼,否則無法作為字元解釋的位元組可能被替換。目標需要 Data URI 時,可以使用 FileReader.readAsDataURL() 獲得字首和資料。

const bytes = new Uint8Array(await file.arrayBuffer());
console.log(bytes.byteLength); // 原始檔案的位元組長度

用往返測試檢查結果

比較還原後的位元組和原位元組,不只比較檔名或截圖。測試應包含空輸入、0 到 255 的全部位元組、中文、emoji,以及末組剩一或兩個位元組的資料。批次處理時每個檔案都要保留獨立狀態,避免失敗結果覆蓋成功檔案。

除非明確呼叫 API,否則轉換可以留在本地。把 Base64 傳送到網路仍然等於傳送可還原的原始資料。瀏覽器方法的行為見 MDN: btoa()。