首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 圖片與 Base64 編碼互轉完整指南:核心 API、工具類封裝與坑點避雷

     編輯:Java 相關知識

前言

Base64 編碼將二進制圖片轉為文本字符串,廣泛用於前端內嵌圖片(Data URI)、API 傳輸、數據庫存儲等場景。本文提供基於 JDK 原生 java.util.Base64(Java 8+)與舊版 sun.misc.BASE64Encoder/Decoder 的完整互轉方案,並封裝為生產級工具類。

核心 API 對比

版本編碼類解碼類備註
Java 8+ (推薦)java.util.Base64.Encoderjava.util.Base64.Decoder標準 API、無依賴、支持 URL/MIME 變體
Java 8 前sun.misc.BASE64Encodersun.misc.BASE64Decoder內部 API、不保證跨 JDK 兼容、編碼輸出含換行符

現代寫法(Java 8+ 推薦)

import java.io.*;
import java.util.Base64;

public class Base64ImageUtils {

    /** 圖片文件 → Base64 字符串 */
    public static String encodeToString(String imagePath) throws IOException {
        byte[] bytes = Files.readAllBytes(Paths.get(imagePath));
        return Base64.getEncoder().encodeToString(bytes);
    }

    /** 圖片文件 → Data URI (前端直接用於 <img src="...">) */
    public static String encodeToDataUri(String imagePath, String mimeType) throws IOException {
        return "data:" + mimeType + ";base64," + encodeToString(imagePath);
    }

    /** Base64 字符串 → 圖片文件 */
    public static void decodeToFile(String base64, String outputPath) throws IOException {
        // 兼容 Data URI 前綴
        if (base64.contains(",")) base64 = base64.split(",")[1];
        byte[] bytes = Base64.getDecoder().decode(base64);
        Files.write(Paths.get(outputPath), bytes);
    }

    /** InputStream → Base64 (適用於上傳流直轉) */
    public static String encodeStream(InputStream in) throws IOException {
        return Base64.getEncoder().encodeToString(in.readAllBytes());
    }
}

舊版寫法(兼容 Java 6/7)

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

public class LegacyBase64Image {
    public static String getImageStr(String imgFilePath) {
        try (InputStream in = new FileInputStream(imgFilePath)) {
            byte[] data = in.readAllBytes(); // Java 9+; Java 8 用 ByteArrayOutputStream 手動讀取
            return new BASE64Encoder().encode(data);
        } catch (IOException e) { throw new RuntimeException(e); }
    }

    public static boolean generateImage(String imgStr, String imgFilePath) {
        if (imgStr == null) return false;
        try {
            byte[] bytes = new BASE64Decoder().decodeBuffer(imgStr);
            // 修正負字節(舊版解碼可能產生負值)
            for (int i = 0; i < bytes.length; i++) if (bytes[i] < 0) bytes[i] += 256;
            try (OutputStream out = new FileOutputStream(imgFilePath)) {
                out.write(bytes);
            }
            return true;
        } catch (Exception e) { return false; }
    }
}

實戰場景示例

場景一:前端 Data URI 直接展示

@GetMapping("/avatar/{userId}")
public String avatarAsDataUri(@PathVariable Long userId) throws IOException {
    String path = userService.getAvatarPath(userId);
    String mime = Files.probeContentType(Paths.get(path)); // image/png, image/jpeg...
    return Base64ImageUtils.encodeToDataUri(path, mime);
}
// 前端: <img src="${avatarUrl}" />

場景二:JSON 接口傳輸圖片

@PostMapping("/upload")
public R upload(@RequestBody Map<String, String> payload) {
    String base64 = payload.get("image"); // 前端 canvas.toDataURL() 獲得
    String fileName = UUID.randomUUID() + ".png";
    Base64ImageUtils.decodeToFile(base64, "/data/uploads/" + fileName);
    return R.ok("https://cdn.example.com/" + fileName);
}

場景三:數據庫存儲 BLOB 的替代方案

將 Base64 字符串存入 TEXT/CLOB 字段,避免 BLOB 流式讀寫複雜性,適合中小圖片(<1MB)。

常見坑點與避雷指南

坑點現象解決
Data URI 前綴干擾解碼解碼報錯/圖片損壞解碼前 split(",")[1] 移除前綴
大文件 OOMHeap 爆滿分塊流式編碼/解碼,勿一次性 readAllBytes
舊版解碼產生負字節圖片顏色錯亂遍歷字節數組 if(b<0) b+=256
編碼輸出含換行符前端解析失敗用 Base64.getEncoder().withoutPadding() 或手動 replaceAll("\\s","")
MIME 類型不匹配瀏覽器不顯示Data URI 必須聲明正確 mimeType

性能優化建議

  • 復用編解碼器: Base64.Encoder/Decoder 線程安全,建議聲明為 static final 復用。
  • 流式處理大文件: 使用 Base64.getEncoder().wrap(outputStream) 邊讀邊寫,避免全量載入內存。
  • 異步處理: 大圖轉換放入線程池,避免阻塞業務線程。

總結

Java 8+ 專案強烈建議遷移至 java.util.Base64,代碼更簡潔、標準、無兼容性風險。封裝通用工具類時,請統一處理 Data URI 前綴、異常轉換、大文件流式化,讓業務代碼保持極簡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved