[指南] 11 min read

[指南] 如何在瀏覽器中預覽 Base64 編碼圖片

五種經過驗證的方法讓 Base64 編碼圖片顯示於頁面 — 直接指派 src、FileReader、canvas、blob 轉換,以及框架專屬模式。包含除錯小撇步。

April 2026 | javascript

// 30 秒解答

如果你手上有一段 Base64 編碼的圖片字串,只想把它顯示在頁面上,最短路徑就是把它當作 data: URI 指派給 img.src。三行 JavaScript 就好:

const img = new Image();
img.src = 'data:image/png;base64,' + base64String;
document.body.appendChild(img);

// If the string already starts with 'data:image/...;base64,'
// — just assign it directly without prepending anything:
img.src = base64StringWithDataUriPrefix;

// 方法一:img.src — 最直接的做法

每個 <img> 元素都把 data URI 視為一般網址。把 URI 指派給 src,瀏覽器會替你完成解碼、格式偵測與渲染。

這對瀏覽器原生支援的任何圖片格式都適用:PNG、JPEG、GIF(動態與靜態)、WebP、SVG、BMP、ICO。Base64 字串可以來自任何地方 — API 回應、localStorage、剪貼簿貼上、資料庫的某一列。

data URI 中的 MIME 類型對於較舊的瀏覽器與某些嵌入式 WebView 很重要。如果你只有原始 Base64 內容(沒有 data: 前綴)且不確定格式,可以探測魔術位元組(見方法五)或預設使用 image/png — 即使 MIME 類型錯誤,大多數瀏覽器仍會嗅探並挽救。

// Plain HTML — no JavaScript needed if the string is static
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." alt="preview">

// Dynamic JavaScript — load from a variable, fetch, or input field
function renderBase64Image(base64, mimeType = 'image/png', containerId = 'preview') {
  const container = document.getElementById(containerId);
  const img = new Image();

  img.onload = () => {
    container.innerHTML = '';
    container.appendChild(img);
  };

  img.onerror = () => {
    container.textContent = 'Invalid image data';
  };

  // Tolerate both raw Base64 and full data: URIs
  img.src = base64.startsWith('data:')
    ? base64
    : `data:${mimeType};base64,${base64}`;
}

renderBase64Image(myBase64String, 'image/jpeg');

// 方法二:用 FILEREADER 處理使用者上傳的檔案

如果使用者透過 <input type="file"> 上傳圖片,你不需要自己手動把它編碼為 Base64。FileReader.readAsDataURL() 會給你一個完整的 data URI,可直接丟進 img.src:

<input type="file" id="fileInput" accept="image/*">
<img id="preview" alt="">

<script>
document.getElementById('fileInput').addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.onload = (event) => {
    // event.target.result is a complete data URI
    // e.g. 'data:image/png;base64,iVBORw0KGgo...'
    document.getElementById('preview').src = event.target.result;
  };

  reader.onerror = () => {
    console.error('FileReader failed:', reader.error);
  };

  reader.readAsDataURL(file);
});
</script>

// 方法三:用 CANVAS 處理生成或修改後的圖片

當你在 <canvas> 上繪製或處理圖片時,canvas.toDataURL() 一個呼叫就能把結果匯出為 data URI。適用於:圖表截圖、簽名板、QR code、浮水印,或任何客戶端生成而你想顯示或下載為圖片的內容。

// 1. Draw on canvas
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#00FF41';
ctx.fillRect(0, 0, 200, 200);
ctx.fillStyle = '#000';
ctx.font = '20px monospace';
ctx.fillText('Hello, Base64!', 20, 100);

// 2. Export to data URI
const pngDataURL = canvas.toDataURL('image/png');
// pngDataURL === 'data:image/png;base64,iVBORw0KGgo...'

// 3. Display directly
const img = new Image();
img.src = pngDataURL;
document.body.appendChild(img);

// JPEG with quality control (0–1)
const jpegDataURL = canvas.toDataURL('image/jpeg', 0.85);

// WebP if supported
const webpDataURL = canvas.toDataURL('image/webp', 0.9);

// 方法四:遠端 BASE64 內容用 FETCH + BLOB

如果 Base64 內容很大(超過 50 KB)或要顯示很多次,透過 URL.createObjectURL() 把它轉成 Blob URL 比把整段 data URI 留在 DOM 裡更省記憶體。Blob URL 短(blob:https://example.com/12345-abcde),不需要時可以撤銷,並且免去 DOM 字串中 33% 的 Base64 額外負擔。

// Convert a Base64 string to a Blob, then to a blob: URL
function base64ToBlobURL(base64, mimeType = 'image/png') {
  // Strip the data: prefix if present
  const payload = base64.includes(',') ? base64.split(',')[1] : base64;

  // Decode Base64 to binary string
  const binary = atob(payload);

  // Convert binary string to Uint8Array
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }

  // Wrap in a Blob and create an object URL
  const blob = new Blob([bytes], { type: mimeType });
  return URL.createObjectURL(blob);
}

// Usage
const blobURL = base64ToBlobURL(myBase64, 'image/jpeg');
const img = new Image();
img.src = blobURL;
document.body.appendChild(img);

// IMPORTANT: free the memory when you're done with the image
img.onload = () => URL.revokeObjectURL(blobURL);

// 方法五:從魔術位元組自動偵測格式

如果你收到一段原始 Base64 內容(沒有 data: 前綴)且不知道它是 PNG、JPEG、GIF 還是 WebP,可以瞄一下解碼後最前面的位元組 — 每種格式都有獨特的特徵碼。

function detectImageFormat(base64) {
  // Look at the first ~12 characters of the Base64 string
  const head = base64.replace(/^data:[^,]+,/, '').slice(0, 16);

  if (head.startsWith('iVBORw0KGgo')) return 'image/png';
  if (head.startsWith('/9j/'))         return 'image/jpeg';
  if (head.startsWith('R0lGOD'))       return 'image/gif';
  if (head.startsWith('UklGR'))        return 'image/webp';
  if (head.startsWith('PHN2Zy') ||
      head.startsWith('PD94bWw'))      return 'image/svg+xml';
  if (head.startsWith('Qk'))           return 'image/bmp';
  if (head.startsWith('AAABAA'))       return 'image/x-icon';

  return 'application/octet-stream'; // unknown
}

// Build a correct data URI even when the user only gave us the payload
function toDataURI(base64) {
  if (base64.startsWith('data:')) return base64; // already complete
  const mime = detectImageFormat(base64);
  return `data:${mime};base64,${base64}`;
}

// REACT — 在元件中顯示 Base64 圖片

在 React 中,把 data URI 當作其他字串 prop 處理即可。若輸入很少變動,可以對轉換結果做 memoize:

import { useMemo } from 'react';

function Base64Image({ base64, mimeType = 'image/png', alt }) {
  const src = useMemo(() => {
    if (!base64) return '';
    return base64.startsWith('data:')
      ? base64
      : `data:${mimeType};base64,${base64}`;
  }, [base64, mimeType]);

  if (!src) return <div>No image</div>;
  return <img src={src} alt={alt} loading="lazy" />;
}

// Usage
<Base64Image
  base64={apiResponse.avatar}
  mimeType="image/jpeg"
  alt="User avatar"
/>

// For large images, prefer blob URLs (Method 4) and useEffect for cleanup:
function LargeBase64Image({ base64 }) {
  const [blobURL, setBlobURL] = useState('');

  useEffect(() => {
    const url = base64ToBlobURL(base64, 'image/png');
    setBlobURL(url);
    return () => URL.revokeObjectURL(url); // cleanup on unmount
  }, [base64]);

  return blobURL ? <img src={blobURL} alt="" /> : null;
}

// VUE 3 — 組合式 API 範例

概念相同,改用 Vue 語法:

<script setup>
import { computed } from 'vue';

const props = defineProps({
  base64: String,
  mimeType: { type: String, default: 'image/png' },
  alt: { type: String, default: '' }
});

const src = computed(() => {
  if (!props.base64) return '';
  return props.base64.startsWith('data:')
    ? props.base64
    : `data:${props.mimeType};base64,${props.base64}`;
});
</script>

<template>
  <img v-if="src" :src="src" :alt="alt" loading="lazy" />
  <div v-else>No image</div>
</template>

// SVELTE — 反應式陳述

<script>
  export let base64 = '';
  export let mimeType = 'image/png';
  export let alt = '';

  $: src = base64
    ? (base64.startsWith('data:') ? base64 : `data:${mimeType};base64,${base64}`)
    : '';
</script>

{#if src}
  <img {src} {alt} loading="lazy" />
{:else}
  <div>No image</div>
{/if}

// 錯誤處理 — 哪些會壞掉,以及為什麼

圖片載入後顯示為破圖佔位符。Base64 內容被截斷、字串中夾雜空白,或標準 data URI 中混入了 URL 安全字元(-_)。請用 str.replace(/\s+/g, '') 去除空白;用 str.replace(/-/g, '+').replace(/_/g, '/') 把 URL 安全變體換回標準;並確認長度正確(Base64 長度必須是 4 的倍數,並有正確的 = 填充)。

圖片能渲染但格式錯誤。data:image/png;base64, 前綴宣稱是 PNG,但實際位元組卻是 JPEG。瀏覽器會嗅探魔術位元組並仍正確渲染 — 但有些 headless 瀏覽器與嵌入式 WebView 不會。請用方法五從位元組偵測真實格式。

圖片在 DOM 中很大,頁面感覺變慢。1 MB 的 Base64 字串放在 React 元件裡,每次狀態更新都會重新渲染。改用 blob: URL(方法四) — 無論圖片大小,在 DOM 中只是 50 字元的字串。

圖片在 Chrome 能用,在 Safari 卻不行。Safari 的 CSP 預設較嚴格,在某些情境下會拒絕 data: URI(<a download>、Service Worker 的 fetch)。請在 Safari 測試,必要時改用 blob: URL。

Base64 字串本身就無效。有時你收到的「Base64」其實是被雙重編碼、十六進位編碼,或單純壞掉了。先把它貼到我們的 Base64 轉圖片解碼器 確認資料有效,再去除錯你的程式碼。

// 效能:data: URI vs blob: URL — 快速基準

以一張 500 KB JPEG 在 <img> 中顯示為例:

用 data: URI 作為 src:DOM 中為 668 KB 字串(33% Base64 額外負擔)。瀏覽器解析 URI、解碼 Base64、解碼 JPEG。在中階筆電上首次繪製約 80 ms。
透過 URL.createObjectURL 取得 blob: URL:DOM 中為 56 字元的字串。瀏覽器抓取記憶體中的 blob、解碼 JPEG。首次繪製約 40 ms。記憶體節省約 50%。

對於一個 5 KB 圖示,差異看不出來 — 兩者都在 5 ms 內渲染完成。要點:約 50 KB 以下,哪個方便用哪個。超過這個界線,優先選 blob URL。

// 隔離測試你的預覽

如果你懷疑有 bug,先把 Base64 字串從應用程式碼中隔離出來。三個快速檢查:

1. 把它貼到我們的線上工具。把字串丟進 Base64 轉圖片轉換器。如果圖片在那邊能正確渲染,代表資料沒問題,bug 在你的程式碼裡。如果在那邊也無法渲染,代表上游就已經損毀。

2. 在新分頁中以網址開啟。複製 data URI(包含 data:image/png;base64, 前綴),貼到新瀏覽器分頁,按下 Enter。現代瀏覽器會直接顯示圖片。(有些會封鎖網址列中的 data: — 那就改用步驟 1 的內嵌測試。)

3. 檢查長度。有效的 Base64 字串長度必須能被 4 整除(去除空白後)。填充字元(=)用來補齊差距:結尾有 0 到 2 個 = 字元。如果長度不是 4 的倍數,字串就是被截斷或多出了東西。

// Quick validation snippet
function looksLikeValidBase64(str) {
  const cleaned = str.replace(/^data:[^,]+,/, '').replace(/\s+/g, '');
  if (cleaned.length === 0) return false;
  if (cleaned.length % 4 !== 0) return false;
  if (!/^[A-Za-z0-9+/]+={0,2}$/.test(cleaned)) return false;
  return true;
}

// 30 秒速查表

最快:把 data URI 指派給 img.src。完成。

來自檔案上傳:FileReader.readAsDataURL(file)

來自 canvas:canvas.toDataURL('image/png')

大型或重複出現的圖片:轉成 blob 並使用 URL.createObjectURL(blob)

未知格式:在組出 data URI 之前,先嗅探魔術位元組(iVBORw0KGgo = PNG、/9j/ = JPEG 等)。

除錯:先貼到 Base64 轉圖片轉換器 — 排除是否是資料本身的問題。

延伸閱讀:認識 Data URI · Base64 圖片嵌入 · JavaScript 中的 Base64:瀏覽器與 Node