若要在 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 輸出與參考字串時非常有用。

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 可讀取的檔案路徑。
- 匯入類別。加入 import java.nio.file.Files;、import java.nio.file.Path;、import java.nio.file.Paths; 以及 import java.util.Base64;,然後將主體包入處理 java.io.IOException 的 try-catch 中。
- 解析路徑。使用 Path path = Paths.get("invoice.pdf"); 建立 Path;視需要將引數替換為絕對路徑,或從引數、組態或環境變數讀取的路徑。
- 讀取位元組。呼叫 byte[] data = Files.readAllBytes(path);;這會將整個檔案載入記憶體,對於現代 JVM 上高達數百 MB 的檔案是可接受的,也是遠低於多數瀏覽器式轉換器 10 MB 門檻的檔案的標準選擇。
- 使用規範編碼器進行編碼。呼叫 String b64 = Base64.getEncoder().encodeToString(data);;結果會是使用標準字母表的 ASCII 字串,以 = 將長度補齊為四的倍數。
- 使用該字串。將 b64 傳遞給 JSON 欄位、HTTP 標頭、資料庫欄位、屬性檔或測試固定資料;將其視為任何其他 ASCII 字串,並記住它大約比原始資料大三分之一。
- 確認大小。以 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(),然後將產生的位元組陣列寫入磁碟。
- 去除輸入可能包裝的任何容器:僅在確定前置詞格式正確時,移除 data: URL 前置詞及其後的逗號;僅在酬載是由 getMimeEncoder() 產生時,才移除 MIME 換行字元。
- 呼叫 byte[] bytes = Base64.getDecoder().decode(encoded);;解碼器要求使用標準字母表加上 = 補齊,且拒絕空白字元、缺少的補齊字元或非零的補齊位元。
- 使用 Path out = Paths.get("decoded.bin"); 建立目的路徑;挑選能反映實際格式的檔名與副檔名,而非 Base64 前置詞。
- 呼叫 Files.write(out, bytes); 以持久化位元組;Files.write 會建立檔案或覆寫現有檔案。
- 當完整性至關重要時,使用適當的應用程式或加密雜湊(例如 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 是可逆的。它不是加密、雜湊、簽署、壓縮、清理或惡意程式掃描。請為每項工作使用真正的原始機制。