若要在 Java 中將檔案轉換為 Base64,請使用 java.nio.file.Files 將檔案讀入位元組陣列,然後傳入 java.util.Base64.getEncoder().encodeToString(bytes);由於自 Java 8 起標準程式庫已內建 java.util.Base64,無需任何第三方相依套件,編碼器會逐字元保留每個位元組,包括零位元組及任意二進位序列,輸出採用 RFC 4648 規範字母表 A–Z、a–z、0–9、加號與斜線,最後一組一律以一個或兩個等號補齊,使結果長度為四的倍數。由於編碼以三個輸入位元組產生四個輸出字元,因此 1024 位元組的檔案會恰好產生 1368 個 Base64 字元(含補齊字元),這就是該輸入長度的規範補齊大小。同一個類別也提供 getDecoder()、getUrlEncoder() 與 getMimeEncoder(),因此只需單一 import 即可使用反向解碼、URL 安全或換行包裝的變體。若不想撰寫測試工具進行快速驗證,基於瀏覽器的 File to Base64 Converter 可在不上傳位元組的情況下,從本機檔案(上限 10 MB)產生相同的規範文字,這在比對 Java 輸出與參考字串時非常有用。

convert file to base64 in java
Convert File to Base64 in Java with java.util.Base64

Java 內建的 Base64 支援(自 Java 8 起)

自 Java 8 起,標準程式庫內含 java.util.Base64,位於 java.base 模組中,因此在 classpath 上不需要額外的相依套件。透過靜態方法公開三個編碼器工廠:getEncoder() 回傳規範的 RFC 4648 編碼器;getUrlEncoder() 回傳 URL 與檔名安全的版本,會將加號替換為減號、斜線替換為底線;getMimeEncoder() 則回傳一個每 76 個字元就以換行包裝,並在最後一行後加上結尾 CRLF 的編碼器,符合傳統的 MIME 規範。三個對應的解碼器則補足了整個 API。

規範編碼器接受位元組陣列,並產生單一的 ASCII 字串,使用標準字母表,當輸入長度不是三的倍數時,會以一個或兩個 = 字元作為補齊字元。由於實作是針對位元組而非字元,因此絕不會解讀內容:JPEG、PDF、加密的 blob 或可執行檔皆可原封不動通過。不會進行行尾轉換、影像重新編碼、UTF-8 正規化、檔案標頭檢查或元資料重寫。此類別為可逆的,因此將編碼後的字串傳入 getDecoder().decode() 即可逐位元地還原原始位元組陣列。

如何在 Java 中將檔案轉換為 Base64

從磁碟上的檔案到 Base64 字串的最短實用路徑,是使用 java.nio.file.Files 載入位元組,並使用 java.util.Base64 進行編碼。以下步驟假設使用 Java 8 或更新版本的工具鏈,以及 JVM 可讀取的檔案路徑。

  1. 匯入類別。加入 import java.nio.file.Files;、import java.nio.file.Path;、import java.nio.file.Paths; 以及 import java.util.Base64;,然後將主體包入處理 java.io.IOException 的 try-catch 中。
  2. 解析路徑。使用 Path path = Paths.get("invoice.pdf"); 建立 Path;視需要將引數替換為絕對路徑,或從引數、組態或環境變數讀取的路徑。
  3. 讀取位元組。呼叫 byte[] data = Files.readAllBytes(path);;這會將整個檔案載入記憶體,對於現代 JVM 上高達數百 MB 的檔案是可接受的,也是遠低於多數瀏覽器式轉換器 10 MB 門檻的檔案的標準選擇。
  4. 使用規範編碼器進行編碼。呼叫 String b64 = Base64.getEncoder().encodeToString(data);;結果會是使用標準字母表的 ASCII 字串,以 = 將長度補齊為四的倍數。
  5. 使用該字串。將 b64 傳遞給 JSON 欄位、HTTP 標頭、資料庫欄位、屬性檔或測試固定資料;將其視為任何其他 ASCII 字串,並記住它大約比原始資料大三分之一。
  6. 確認大小。以 4 * ceil(bytes.length / 3) 計算預期的字元數;若實際長度不符,表示該編碼器並非 RFC 4648 規範,接收端系統可能會拒絕它。

對於 1024 位元組的檔案,預期的 Base64 長度為 4 * ceil(1024 / 3) = 4 * 342 = 1368 個字元,包含最後一組的兩個補齊字元。編碼會使酬載大約增加三分之一,因此 1 MB 的檔案會變成約 1.33 MB 的文字。請據此規劃日誌行、工單欄位與資料庫欄位。

java.util.Base64 中的編碼器與解碼器變體

方法字母表補齊換行包裝典型用途
getEncoder()A–Z a–z 0–9 + /需要 =規範的 RFC 4648 輸出、JSON 欄位、標頭
getUrlEncoder()A–Z a–z 0–9 - _需要 =查詢字串、檔名、URL 中的權杖
getMimeEncoder()A–Z a–z 0–9 + /需要 =每 76 字元 + 結尾 CRLF電子郵件本文、MIME 附件、傳統傳輸方式
getDecoder()僅限標準 + /嚴格拒絕空白字元getEncoder() 的反向操作
getUrlDecoder()僅限 URL 安全 - _嚴格拒絕空白字元getUrlEncoder() 的反向操作
getMimeDecoder()僅限標準 + /嚴格忽略換行字元getMimeEncoder() 的反向操作

請挑選與接收端預期相符的編碼器。常見的錯誤是將 MIME 包裝的輸出傳送給不會去除換行的 JSON 解析器,或是將 URL 安全的輸出傳送給只認得加號與斜線的解碼器。如有疑慮,規範的 getEncoder() 加上 getDecoder() 配對是最安全的預設選擇。

在 Java 中將 Base64 解碼回檔案

反向操作與編碼路徑互為鏡像。讀取編碼後的字串,將其交給 getDecoder().decode(),然後將產生的位元組陣列寫入磁碟。

  1. 去除輸入可能包裝的任何容器:僅在確定前置詞格式正確時,移除 data: URL 前置詞及其後的逗號;僅在酬載是由 getMimeEncoder() 產生時,才移除 MIME 換行字元。
  2. 呼叫 byte[] bytes = Base64.getDecoder().decode(encoded);;解碼器要求使用標準字母表加上 = 補齊,且拒絕空白字元、缺少的補齊字元或非零的補齊位元。
  3. 使用 Path out = Paths.get("decoded.bin"); 建立目的路徑;挑選能反映實際格式的檔名與副檔名,而非 Base64 前置詞。
  4. 呼叫 Files.write(out, bytes); 以持久化位元組;Files.write 會建立檔案或覆寫現有檔案。
  5. 當完整性至關重要時,使用適當的應用程式或加密雜湊(例如 SHA-256)驗證結果,因為副檔名並不會檢查位元組內容。

嚴格解碼之所以重要,是因為同一份酬載可以用幾種看似有效的方式拼寫。java.util.Base64 中的解碼器會對結果重新編碼並進行比對,以強制執行規範形式;非規範的輸入會拋出 IllegalArgumentException,而不是靜默地產生不同的位元組陣列。

使用本機瀏覽器工具驗證 Java 輸出

在服務之間傳送 Base64 之前,確認 Java 輸出與參考字串逐位元相同是很有幫助的。本機瀏覽器的 File to Base64 Converter 接受上限 10 MB 的檔案,並產生相同的規範 RFC 4648 補齊文字,全程皆在當前分頁中完成,不上傳任何位元組,這在與規格或測試固定資料中的預期值進行比對時非常有用。對於反向操作,同一個工具接受不含空白字元的規範 Base64,由您提供檔名與 MIME 類型,並產生一個可下載與檢查的臨時 Blob URL。

會保留不會執行
來源的精確位元組內容轉碼影像或重寫媒體
零位元組與任意二進位資料正規化行尾字元
原始檔案格式與標頭檢查或推斷檔案格式
必要的 RFC 4648 補齊新增 data: URL 前置詞
規範的零補齊位元插入 76 字元的換行包裝

由於瀏覽器透過 W3C File API 以 ArrayBuffer 形式讀取檔案,絕不會將位元組傳送至伺服器,因此您可以使用與執行 Java 程式碼相同的可信賴機器。對於包含憑證、個人資料、簽署金鑰或可執行酬載的檔案,請避免使用共用或不受信任的機器:Base64 是編碼而非保護,產生的字串仍然能承載原始檔案的所有內容。若要更深入了解規範輸出與嚴格解碼器行為,RFC 4648 規範輸出逐步解說 與本指南搭配閱讀效果絕佳。

關於補齊與補齊位元的陷阱

規範的 RFC 4648 輸出以零、一或兩個 = 字元結尾,使編碼長度為四的倍數。當最後一組包含一個輸入位元組時,會產生兩個字元與兩個補齊符號;當包含兩個輸入位元組時,則產生三個字元與一個補齊符號。省去補齊或接受格式錯誤補齊的解碼器,可能會掩蓋輸入中的實際差異。更嚴格的問題是非零的補齊位元:最後一個字元中未使用的位元不承載任何資訊,因此規範的編碼器一律將其寫為零;若傳送端寫入非零值以夾帶資料,解碼器必須拒絕該輸入。RFC 4648 定義了字母表、補齊規則,以及用於鎖定正確性的測試向量,包括空字串、f、fo、foo、foob、fooba 與 foobar 等字串。

  • 混用字母表。URL 安全與標準字母表不可互換。預期接收加號與斜線的接收端會在遇到減號與底線時失敗。
  • 保留換行字元。getEncoder() 絕不會插入換行,但許多複製貼上的來源會在 76 個字元處換行;嚴格的 getDecoder() 會拒絕這些輸入,除非您改用 getMimeDecoder(),或先去除換行字元。
  • 輕信檔名。解碼後的位元組本身沒有副檔名;將 decoded.bin 重新命名為 decoded.pdf 並不會使其變成 PDF。請使用正確的應用程式開啟檔案,或計算雜湊值。
  • 混淆編碼與安全性。Base64 是可逆的。它不是加密、雜湊、簽署、壓縮、清理或惡意程式掃描。請為每項工作使用真正的原始機制。