Base64 圖片不顯示?10 個常見原因與修復清單
發佈於 2026 年 4 月 28 日 · 閱讀約 8 分鐘
圖片已經轉成 Base64,data URI 也塞進了 HTML——結果什麼都沒顯示。只看到一個裂圖標。更離譜的是:Chrome 能顯示,Safari 不行;本機能跑,部署就掛。
Base64 圖片顯示失敗之所以令人抓狂,是因為字串看起來完全正常。真正的原因往往藏在細節裡:前綴少了一個字元、複製貼上時混入了不可見的空白、或者後端偷偷做了二次編碼。本文涵蓋全部 10 種常見原因,每種都附帶程式碼範例和修復方法。
速查表:症狀 → 原因 → 修復
先從這裡開始。找到你的症狀,定位可能的原因,再跳到下方看詳細修復。
| # | 症狀 | 可能原因 | 快速修復 |
|---|---|---|---|
| 1 | 404 / 裂圖標 | 缺少 data: 前綴 | 補上 data:image/...;base64, |
| 2 | 空白 / 不渲染 | ; 寫成了 , | 修正前綴中的分號 |
| 3 | 空白 / 不渲染 | base64 後缺逗號 | 補上逗號:base64, |
| 4 | 圖片殘缺 / 損壞 | 字串被截斷 | 改用 TEXT 欄位類型 |
| 5 | InvalidCharacterError | 混入空格 / 非法字元 | str.replace(/\s/g, '') |
| 6 | 程式碼裡正常,HTML 裡掛了 | 換行符 \n 污染 | 去掉 \r\n |
| 7 | 不同瀏覽器行為不一致 | Padding = 被吃掉 | URL 編碼或手動補齊 |
| 8 | 通常不會掛 | MIME 類型不匹配 | 修正即可,非元兇 |
| 9 | 裂圖標,字串長了 ~33% | 雙重編碼 | 去掉多餘的編碼步驟 |
| 10 | 裂圖標,字串含 \/ | JSON / URL 跳脫污染 | 用 JSON.parse() |
前綴出錯:data: URI 寫法有誤
data URI 的語法要求非常嚴格。錯一個字元,瀏覽器就會把你的 Base64 字串當作一個壞掉的 URL,而不是圖片資料。
原因 1:整段 data URI 前綴缺失
如果直接把裸的 Base64 字串賦給 src,沒有加 data:image/...;base64, 前綴,瀏覽器會把它當成相對路徑去請求——結果就是 404。
❌ <img src="iVBORw0KGgo..." />
✅ <img src="data:image/png;base64,iVBORw0KGgo..." /> 原因 2:分號寫成了逗號
寫成 data:image/png,base64,... 而不是 data:image/png;base64,...,瀏覽器會把 base64,... 當作純文字內容,而不是 Base64 編碼標識。
❌ data:image/png,base64,iVBORw0KGgo...
✅ data:image/png;base64,iVBORw0KGgo... 原因 3:"base64" 後面漏了逗號
base64 和實際資料之間的逗號不能省。如果寫成 data:image/png;base64iVBOR...,瀏覽器會把 base64iVBOR... 當作字元集名稱,而不是編碼資料。
❌ data:image/png;base64iVBORw0KGgo...
✅ data:image/png;base64,iVBORw0KGgo... 編碼損壞:Base64 字串本身有問題
即使前綴完全正確,編碼後的資料也可能在儲存、傳輸或複製貼上過程中被悄悄破壞。
原因 4:字串被截斷
資料庫欄位有長度上限(例如 VARCHAR(65535)),會靜默截斷 Base64 字串。一張 100KB 的 PNG 編碼後約 136,000 個字元——如果欄位在 65,535 處截斷,解碼出來的圖片直接是壞的。修復:儲存 Base64 請使用 TEXT 或 LONGTEXT 類型。
原因 5:混入了非法字元(空格、特殊符號)
合法的 Base64 只包含 A-Z、a-z、0-9、+、/ 和 =。複製貼上時混入的空格會導致 atob() 直接拋出 InvalidCharacterError。修復:使用前先去掉所有空白字元:str.replace(/\s/g, '')。
原因 6:換行符污染
openssl base64 預設每 76 個字元插入一個 \n(遵循 RFC 2045)。這些換行符在 HTML 的 data URI 裡會導致解碼失敗。修復:使用 openssl base64 -A(單行輸出),或去掉換行:str.replace(/[\r\n]/g, '')。
原因 7:Padding 被 URL 解析吃掉
Base64 末尾的 = 填充字元在通過 URL 參數傳遞時經常被吞掉,因為 = 在 URL 中是保留字元。有些瀏覽器能容忍缺失的 padding,有些不行——導致跨環境行為不一致。修復:放入 URL 前先做 encodeURIComponent(),或在接收端手動補齊 padding。
MIME 類型不匹配:真的會掛嗎?
這條可能會讓你意外:宣告了錯誤的 MIME 類型,大多數情況下圖片依然能正常顯示。
原因 8:宣告的 MIME 與真實檔案類型不一致
如果你寫了 data:image/png;base64,/9j/4AAQ...(JPEG 資料卻宣告為 PNG),大多數現代瀏覽器依靠內容嗅探(content sniffing)依然能正確渲染。但有兩種場景確實會出問題:(1) 設定了嚴格 CSP 且啟用了 MIME 強制校驗,(2) 伺服端按宣告的 MIME 做格式轉換,導致輸出損壞。結論:修好它是正確做法,但它極少是顯示失敗的真正元兇。
鏈路問題:資料到達瀏覽器前就已經壞了
這類問題最難排查,因為你程式碼裡的 Base64 字串看起來完全正常——損壞發生在序列化或傳輸環節。
原因 9:雙重 Base64 編碼
後端對已經編碼過的資料又做了一次 Base64 編碼,結果變成了對 Base64 字串再做一次 Base64。長度比預期多 ~33%,解碼一次後得到的是文字而不是二進位圖片資料。識別方法:解碼一次,如果結果看起來還是 Base64(字母開頭、= 結尾),說明被雙重編碼了。修復:去掉後端處理鏈路中多餘的編碼步驟。
原因 10:JSON 跳脫或 URL 編碼污染
Base64 字串包含 / 字元。某些 JSON 序列化器會把它跳脫為 \/。如果前端沒有用 JSON.parse 正確解析,而是直接取原始字串,多出來的反斜線就會污染資料。類似地,通過 URL 參數傳遞 Base64 時,+ 會變成空格,= 會被吞掉。修復:JSON 資料務必使用 JSON.parse()。URL 傳輸使用 encodeURIComponent()。
系統排查範本
如果以上原因都沒命中,按以下步驟逐項排查:
- 在瀏覽器網址列測試 data URI — 把完整的
data:image/...;base64,...字串直接貼到網址列。如果能顯示,說明問題出在應用注入字串的方式上。 - 檢查瀏覽器主控台 — 按 F12,在 Console 標籤頁查找
net::ERR_INVALID_URL或 CSP 違規等錯誤訊息。 - 比對字串長度 — 對比源頭(後端)和前端拿到的 Base64 字串長度。如果不一致,說明傳輸過程中發生了截斷或損壞。
- 解碼並檢查 — 在主控台用
atob()解碼前幾個字元。如果拋出InvalidCharacterError,說明字串中混入了非法字元。 - 檢測雙重編碼 — 解碼一次。如果結果看起來還像 Base64 字串,再解碼一次。如果第二次解碼得到了二進位資料,說明處理鏈路中存在多餘的編碼步驟。
用 ViewJSON 一鍵驗證 Base64
與其手動檢查 Base64 字串,不如直接把 JSON 貼到 ViewJSON。它透過魔數偵測自動識別 Base64 編碼的媒體並渲染行內預覽——如果預覽正常出現,說明你的 Base64 是有效的;如果沒有,你可以精確定位是哪個欄位出了問題。
相關文章
優雅地偵錯 JSON API 回應中的 Base64 圖片 →立即體驗
貼上你的 Base64 字串,立刻驗證是否能正確渲染——完全在瀏覽器中完成,無需上傳。
開啟 ViewJSON →