跳至主要內容
Skip to content

Blob vs Base64 — 同一份資料的兩種面貌

在 Web 開發(特別是處理圖片、檔案上傳)中,Blob 與 Base64 是兩個最常見的名詞。簡單來說,它們是 「同一份資料的兩種不同表現形式」

  • Blob (Binary Large Object):電腦看檔案的方式(二進位、原始資料)
  • Base64:為了讓人類或特定傳輸協定方便處理而轉成的「字串」(純文字)

**比喻**

想像你打客服電話報訂單編號 A7B3

  • Blob 就像直接快速唸出 「A-7-B-3」。簡短高效,但電話那頭可能聽成「A-7-D-3」或「8-7-B-3」。
  • Base64 就像改說 「A-Apple、7、B-Boy、3」。內容變長了,但能確保對方在「只靠聲音」的通道中準確接收,不會出錯。

一、 核心差異比較表

特性Blob (Binary Large Object)Base64 (Data URL)
本質原始二進制資料 (0 和 1)純文字字串 (ASCII)
檔案大小原始大小 (較小)變大約 33% (因為編碼膨脹)
主要用途檔案上傳 (FormData)、下載檔案、影片串流嵌入小圖示 (Icon)、存入 localStorage、JSON 傳輸
記憶體消耗低 (瀏覽器優化)高 (需解析巨型字串)
渲染方式需透過 URL.createObjectURL() 轉成網址直接放入 src (data:image/png;base64...)

二、 為什麼 Blob 無法直接塞進 HTML/JSON?

這是因為 Blob 是「二進位世界」的居民,而 HTML/CSS/JSON 是「文字世界」的產物。如果不經過轉換,直接把 Blob 硬塞進去,會發生三個致命問題:

1. 語法崩壞 (Syntax Breaking)

HTML、CSS 和 JSON 都是基於 純文字 (Text-based) 的格式,它們依賴特定的「特殊符號」來定義結構:

  • HTML 依賴 <>
  • CSS 依賴 {}
  • JSON 依賴 " (雙引號) 和 , (逗號)

Blob (二進制資料) 是由 0 到 255 的位元組(Bytes)組成。在這些二進位數據中,很有可能剛好包含代表 <"} 的代碼。

> **災難場景**

假設你硬要把一張圖片的二進制資料塞進 HTML 的 src 屬性裡:

html
<img src="...[圖片二進制資料]..." />

如果圖片資料裡剛好有一個 byte 是 0x22 (也就是雙引號 "),瀏覽器會以為屬性結束了,導致後面的資料被當成 HTML 標籤解析,造成網頁結構瞬間瓦解。

2. JSON 的序列化限制

JSON (JavaScript Object Notation) 的標準規範極度嚴格,它只支援以下幾種資料型態:

  • 字串 (String)
  • 數字 (Number)
  • 布林值 (Boolean)
  • 陣列 (Array)
  • 物件 (Object)
  • null

JSON 不支援「Binary」型別。

當你嘗試在 JavaScript 中把一個 Blob 物件轉成 JSON 字串時:

javascript
const blob = new Blob(["Hello"], { type: "text/plain" });
const json = JSON.stringify({ file: blob });

console.log(json);
// 輸出結果: {"file":{}}

結果是空的! 因為 Blob 是一個指向記憶體(或硬碟)的「複雜物件參照」,它不是純資料值。JSON.stringify 不知道該如何把這個「記憶體指針」變成文字,所以直接忽略它。

3. 傳輸協定的字元編碼問題

HTML/CSS/JSON 通常使用 UTF-8 編碼來儲存和傳輸。UTF-8 是針對文字設計的編碼,並非所有的二進位 byte 序列都是合法的 UTF-8 字元。

如果你把原始的 Blob 二進制資料直接當作文字讀取:

  1. 會出現大量的 亂碼
  2. 會出現 控制字元(如 NULL byte, \0),這在許多程式語言中代表「字串結束」,導致資料讀取只到一半就被截斷

三、 那我們該怎麼辦?

因為「水(Blob)」不能直接裝進「紙袋(HTML/JSON)」裡,我們有兩種標準做法:

方法 A:把水結成冰(轉成 Base64)

把二進制資料編碼成只有 a-zA-Z0-9+/ 組成的安全字串。

  • 優點:可以直接放進 JSON、CSS (background-image: url(...)) 或 HTML 裡
  • 缺點:體積變大 33%,解析耗效能

方法 B:給水一個門牌號碼(Blob URL)

不把資料放進 HTML,而是產生一個連結 blob:http://localhost/...

javascript
const url = URL.createObjectURL(file);
// url = "blob:http://localhost:3000/550e8400-e29b-41d4-a716-446655440000"
  • 原理:告訴 HTML:「圖片不在這裡,請去記憶體的這個地址找」
  • 優點:效能極佳,HTML 依然保持乾淨的文字格式
  • 限制:只能在當前瀏覽器頁面使用,無法存進 JSON 傳給後端

四、 實戰建議:該選哪一個?

如果是「檔案上傳」:使用 Blob

當你要把使用者選的照片傳給後端 API 時,絕對建議使用 Blob

  • 原因:透過 FormData 傳送 Blob 是標準的 multipart/form-data 格式,伺服器不需要額外解碼 Base64,且傳輸量小 33%

如果是「圖片預覽」:使用 Blob URL

早期大家習慣轉 Base64 做預覽,但現在更推薦使用 Blob URL (Object URL)

javascript
const url = URL.createObjectURL(file);
imageElement.src = url;
  • 原因:這是瀏覽器內部的指針,幾乎不消耗效能,瞬間產生。Base64 轉換大圖時會造成 UI 卡頓
  • 注意:用完記得釋放 URL.revokeObjectURL(url)

如果是「極小的圖示」:使用 Base64

  • 原因:如果圖片只有 1-2KB,為了省去一次 HTTP Request,可以直接將 Base64 寫死在 CSS 或 HTML 裡

總結

情境推薦方案理由
檔案上傳Blob + FormData傳輸量小、伺服器無需解碼
圖片預覽Blob URL效能極佳、瞬間產生
存入 localStorageBase64localStorage 只能存字串
極小圖示 (< 2KB)Base64省一次 HTTP Request
JSON API 傳輸圖片Base64 或改用 FormDataJSON 不支援 Binary
  • Blob 是為了 效能與傳輸(給機器與網路用的)
  • Base64 是為了 方便嵌入與文字化(給 HTML/CSS 或 JSON 用的)

← 返回專題首頁 | 下一章:從 0/1 到 0-255 →