Base64 會把一份完整的 SVG 文件,轉換成一串 data:image/svg+xml;base64 字串,讓這個向量檔案能存在於 HTML、CSS 或 JavaScript 之中,而不需要另外發出一次 HTTP 請求。這項轉換是一種由RFC 4648所定義的純文字對文字運算:來源 SVG 每三個位元組,會變成四個 Base64 字元,因此在加上資料網址前綴之前,編碼後的輸出大約會比原始檔案大三分之一。Unicode 字元、帶重音符號的拉丁字母、CJK 字形與 emoji,會先被編碼成 UTF-8 位元組,再對這些位元組做 Base64 編碼。這條完全可逆的路徑是:SVG 原始碼 → UTF-8 位元組 → Base64 字元 → 資料網址。反向流程則是取一段對應的資料網址,去掉前綴,解碼 Base64,並在回傳 SVG 文字之前,驗證這些位元組是合法的 UTF-8。SVG to Base64 轉換器正是在你的瀏覽器裡完成這項轉換,不需要上傳、不會渲染,也不會靜默地清理來源文件。

how to convert svg image to base64
how to convert svg image to base64

SVG 資料網址的結構解析

資料網址是一整行文字,其中包含媒體類型、編碼標籤與主體酬載。對 SVG 而言,標準化的形式是 data:image/svg+xml;base64,<payload>,前綴會告訴接收端後面跟著的是什麼樣的位元組,以及它們是如何產生的。酬載是這個 SVG 經過 Base64 編碼後的 UTF-8 位元組序列,而前綴本身並不屬於已編碼的位元組;解碼器會先把它去掉,再反轉編碼過程。根據 RFC 4648,Base64 是一套二進位轉文字的字母表,而不是一種壓縮格式,因此酬載一定會比原始位元組長度更大。

從這個結構,可以得出幾個實務上的影響:

  • 來回轉換的兩端,都需要相同的前綴。一個缺漏、打錯,或使用了不同前綴的情況,會被嚴謹的解碼器拒絕,而不是靜默地產生一個錯誤的結果。
  • 酬載是不透明的 ASCII 內容。原始的 SVG 標記,在資料網址內部並不是人類可讀的形式,也無法在不解碼的情況下,於程式碼審查中比對差異。
  • 資料網址是單一一串字串,不含任何對外部檔案的參照,因此這個 SVG 所需要的任何資源(字型、圖片、腳本),都必須內嵌其中,或是能從嵌入的環境中取得。

如何把 SVG 轉換成 Base64

  1. 在你的瀏覽器中打開 SVG to Base64 轉換器。選擇編碼方向。
  2. 把一份完整的 SVG 文件貼進來源區域。這項工具要求輸入內容含有一個完整、附有結束標籤的 svg 根元素,在去除可選的 UTF-8 位元組順序記號與周圍空白之後判斷。它並不要求特定的命名空間宣告,但你提供的命名空間、屬性與元素內容,都會原樣保留。
  3. 執行轉換。這項工具會使用瀏覽器的 TextEncoder,把 Unicode 文字編碼成 UTF-8 位元組,以有限的區塊處理這些位元組,再把這些區塊 Base64 編碼成單一一串輸出字串。
  4. 檢查完整的文字結果。回傳的字串,會以確切的前綴 data:image/svg+xml;base64, 開頭,接著是 Base64 酬載。如果你需要確認編碼是否正確,可以核對酬載開頭的幾個字元,是否符合一個已知的往返測試結果。
  5. 複製完整的資料網址。把它貼到實際要使用的確切位置:img 的 src、CSS 的 background-image: url(...) 宣告、JavaScript 字串,或是建置時的樣板。
  6. 在正式上線前,於真實的接收端測試渲染結果。打開頁面或預覽畫面,確認 SVG 能正常渲染,並檢查瀏覽器主控台是否有 CSP 或混合內容方面的錯誤。

來源輸入內容的上限是 500,000 個字元。產生出來的資料網址,仍然有可能超過目標網站的政策、標頭大小限制,或是你目的地所設下的任何更小的容量預算,因此在你決定採用內嵌方式之前,請先規劃好測試這一步。

把編碼後的輸出讀回原文

當你手上有一個從建置工具、CMS 匯出功能,或樣式表繼承而來的資料網址,想把原始的 SVG 還原出來編輯時,反向流程就派得上用場。轉換器會用相同的三個步驟處理這個情境,只是選擇「解碼」方向,而不是「編碼」。

方向 輸入 輸出 驗證步驟
編碼 完整的 SVG 文件(UTF-8 文字) data:image/svg+xml;base64,... 字串 去除 BOM,驗證 svg 根元素結構
解碼 確切的 data:image/svg+xml;base64,... 字串 UTF-8 SVG 文字 對解碼後的位元組進行嚴格的 UTF-8 驗證

解碼器只接受確切的前綴。它不會嘗試猜測純 Base64、經過網址編碼的 SVG、其他媒體類型參數,或是經過空白正規化的酬載。這種嚴格限縮的輸入規範,能避免意外解碼到不相關的資料,並讓往返行為在各個瀏覽器之間保持一致。如果輸入內容不符合,轉換器會回傳一個錯誤,而不會嘗試修補前綴,或用替代字元頂替。

為什麼編碼後的輸出,會比來源更大

Base64 為來源資料的每六個位元,分配一個 ASCII 字元。三個來源位元組(24 個位元),會變成四個 Base64 字元,這就是驅動體積增長的規則。對一個小型 SVG 而言,這個算法很直接。

一個 300 位元組的 SVG,會產生 300 / 3 * 4 = 400 個 Base64 字元,再加上 26 個字元的 data:image/svg+xml;base64, 前綴,總計大約 426 個字元。這大約比來源位元組多出 42%,還不包括當輸入長度無法被三整除時,演算法所加上的任何填補 = 字元。

這種膨脹並不是一個錯誤。Base64 的文件明確說明它是一種二進位轉文字的表示方式,而不是壓縮,而WHATWG 編碼標準則定義了 Base64 所消耗的 UTF-8 位元組序列。這種增長,是把二進位資料搬運到純文字通道所付出的代價。特別針對 SVG,這帶來兩個實務上的後果:

  • 以獨立檔案提供的 SVG,可以透過 HTTP 內容編碼(通常是 gzip 或 Brotli)壓縮。同一個 SVG 以 Base64 資料網址內嵌時,通常會以未壓縮的形式提供,因此傳輸體積的增長,會比單純的 Base64 膨脹幅度還要更大。
  • 資料網址無法獨立於主文件被快取。如果同一個 SVG 出現在多個頁面上,每個頁面都會各自帶著自己的一份副本。

比較可靠的做法,是實際量測連同資料網址在內的 HTML、CSS 或 JavaScript 最終傳輸大小,而不是假設內嵌一定比較快。對於較大、可重複使用的素材,一個能被獨立快取的 SVG 檔案,幾乎永遠是更好的選擇。

Unicode、UTF-8 與特殊字元

SVG 文件經常包含非 ASCII 字元:text 元素裡帶重音符號的拉丁文字、CJK 標籤、emoji,或是註解。這些內容都必須先被編碼成 UTF-8 位元組,才能進行 Base64 編碼。一個常見的失誤模式,是直接把一個 JavaScript 字串傳給只支援 Latin-1 的 Base64 輔助函式,因為每個字元都被當作一個位元組處理,這會靜默地損毀超過 255 的碼位。

這款轉換器使用瀏覽器的 TextEncoder 產生一段 UTF-8 位元組序列,以有限的區塊處理這些位元組以避免引數清單過大,再套用 Base64 編碼。在解碼那一側,這段位元組序列,會經過一個嚴格的 UTF-8 驗證器檢查。格式錯誤的 UTF-8,會產生一個明確的錯誤,而不是替換字元 U+FFFD,因為後者會製造出一個看似成功、實則有問題的假性往返結果。

原始文字 UTF-8 位元組數 Base64 字元數
僅 ASCII(例如簡單標記) 每個字元 1 個位元組 每 3 個位元組對應 4 個字元
帶重音符號的拉丁字母(例如 é) 每個字元 2 個位元組 每 3 個位元組對應 4 個字元
CJK 與多數 emoji 每個字元 3 或 4 個位元組 每 3 個位元組對應 4 個字元

位元組對字元的比例,是由 Base64 本身固定下來的;來源字元的類型,只會影響來源文字在進入 Base64 編碼之前,會膨脹成多少位元組。既然編碼標準已經指定了 UTF-8 位元組輸出,一旦你知道位元組數,同樣的三分之一公式就適用。

資料網址最適合用在哪裡(以及該跳過的時候)

當向量圖檔很小、用途單一,且與特定文件綁定時,Base64 SVG 資料網址就很有用。常見的適用情境包括:單一頁面或樣板中的內嵌圖示與標誌,此時多發出一次 HTTP 請求,會比體積增長的成本更高;電子郵件範本,因為許多郵件用戶端會封鎖外部圖片,而資料網址則會隨著郵件一起傳送;伺服器端渲染的 HTML,其中 SVG 是由使用者控制的資料所建構出來的,資料網址是注入結果最簡單的方式;以及 CSS 展示範例與 CodePen 風格的程式碼片段,這些情境中,原始碼的可讀性,遠不如貼上即用來得重要。

當 SVG 檔案很大、在許多頁面中重複使用,或屬於設計系統的一部分時,就該跳過內嵌。一個搭配妥善 HTTP 快取、內容編碼與穩定網址的獨立檔案,幾乎永遠都更便宜、更容易除錯。轉換器裡 500,000 字元的來源上限,也隱含了你所能產生的資料網址的一個上限;如果你的成品超過這個限制,走檔案路徑才是正確的做法。

安全性:Base64 做得到什麼、做不到什麼

Base64 是一種呈現格式,而不是一道安全邊界。對一個 SVG 做編碼,並不會清理它,不會去除腳本,也不會封鎖外部資源。腳本、事件處理器、foreignObject 內容、連結、外部字型參照,以及濾鏡基元,全都會原封不動地留在資料網址裡,一旦結果被嵌入到一個會執行它們的環境中,就會再次變成可執行的狀態。

這款轉換器絕不會預覽或執行你提供的 SVG,這消除了在轉換步驟中意外執行程式碼的立即風險。但風險會轉移到嵌入的那個網站上。具體來說,在沒有一套妥善維護的清理流程,以及一套針對該情境設計的內容安全政策之前,請不要把不受信任的 SVG 輸出,放進 iframe、object、DOM,或是任何 CSS 屬性裡。請把這個資料網址,當作你會如何對待原始 SVG 檔案一樣看待:如果你不會把這個檔案放上你的網站,那也不應該把這個資料網址嵌入進去。對於不受信任的 SVG,請使用一個獨立、沙盒化的服務環境,搭配嚴格的標頭與一套持續維護的清理器。單靠編碼本身,並不能提供任何保護。

在真實的目的地測試結果

轉換本身是在本機完成的,但真正重要的,是目的地實際上會如何處理這個資料網址。在正式上線之前,請確認以下三件事。

  1. 目的地的內容安全政策,允許使用這個資料網址。有些網站會在 CSS、內嵌腳本,或圖片情境中,完全封鎖 data: 這種格式的網址。img-src 'self' data: 是常見的設定值,能允許內嵌的 SVG 圖片。
  2. 沒有超出目的地的容量預算。標頭、資料庫欄位、QR code,以及樣板引擎,都各自有自己的限制,這些限制並不會因為轉換器的 500,000 字元來源上限而被排除。
  3. 這個 SVG 在嵌入的環境中,渲染方式與作為獨立檔案時相同。一個經過清理的 Markdown 渲染器、一個嚴格的 CSS 解析器,或一個精簡過的郵件用戶端,對腳本、濾鏡,或外部參照的反應,可能會與一個完整瀏覽器有所不同。

如果渲染出來的結果出現落差,應該檢查的是原始的 SVG,而不是這個資料網址。編碼過程是確定性且可逆的;差異來自嵌入的環境,而不是來自轉換過程本身。

相關閱讀:如何不寫程式碼、在 Java 中解析網址