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

Java MySQL BLOB 存取圖片完整實戰指南

     編輯:Java 相關知識

Java 操作 MySQL BLOB 類型存取圖片完整教學

在許多應用系統中,需要將圖片、文檔等二進制文件直接存儲在資料庫中。MySQL 提供 BLOB(Binary Large Object)類型支援此需求。本文詳細說明 BLOB 類型選擇、Java 讀寫代碼實作、常見問題與最佳實踐。

MySQL BLOB 類型對照表

四種 BLOB 類型僅最大儲存長度不同,請根據文件大小選擇:

類型最大長度適用場景
TINYBLOB255 bytes極小圖示、縮圖
BLOB64 KB小圖片、配置文件
MEDIUMBLOB16 MB一般照片、文檔
LONGBLOB4 GB高解析度影像、大型文件

資料表結構範例

CREATE TABLE phototest (
    id INT PRIMARY KEY,
    photo LONGBLOB NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Java 完整存取實作

import java.io.*;
import java.sql.*;

public class ImageBlobDemo {
    // 資料庫連線配置(實際專案請使用連線池與外部配置)
    private static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASSWORD = "password";

    public static void main(String[] args) {
        String sourceImage = "source.png";
        String targetImage = "retrieved.jpg";
        int recordId = 1;

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {
            // 1. 存入圖片
            storeImage(conn, recordId, sourceImage);
            System.out.println("圖片存入成功");

            // 2. 讀取圖片
            retrieveImage(conn, recordId, targetImage);
            System.out.println("圖片讀取成功:" + targetImage);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 將本地圖片存入資料庫
     */
    public static void storeImage(Connection conn, int id, String imagePath) 
            throws SQLException, IOException {
        String sql = "INSERT INTO phototest (id, photo) VALUES (?, ?) " +
                     "ON DUPLICATE KEY UPDATE photo = ?";
        
        try (PreparedStatement ps = conn.prepareStatement(sql);
             FileInputStream fis = new FileInputStream(imagePath)) {
            
            ps.setInt(1, id);
            ps.setBinaryStream(2, fis, fis.available());
            ps.setBinaryStream(3, fis, fis.available()); // 更新用
            ps.executeUpdate();
        }
    }

    /**
     * 從資料庫讀取圖片至本地
     */
    public static void retrieveImage(Connection conn, int id, String outputPath) 
            throws SQLException, IOException {
        String sql = "SELECT photo FROM phototest WHERE id = ?";
        
        try (PreparedStatement ps = conn.prepareStatement(sql);
             FileOutputStream fos = new FileOutputStream(outputPath)) {
            
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    try (InputStream is = rs.getBinaryStream("photo")) {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = is.read(buffer)) != -1) {
                            fos.write(buffer, 0, bytesRead);
                        }
                    }
                } else {
                    throw new SQLException("找不到 ID=" + id + " 的記錄");
                }
            }
        }
    }
}

關鍵技術點解析

1. 使用 setBinaryStream / getBinaryStream

避免一次性將大文件載入記憶體(setBytes()/getBytes()),流式處理支援任意大小文件,記憶體佔用恆定。

2. 防止資料截斷異常

若遇到 Data truncation: Data too long for column,請檢查:

  • BLOB 類型是否足夠大(建議直接用 LONGBLOB)
  • MySQL 配置 max_allowed_packet 是否足夠(預設 4MB,大文件需調大)

3. 連線池與資源管理

生產環境必須使用 HikariCP、Druid 等連線池,並利用 try-with-resources 確保連線、流正確關閉。

效能與架構建議

策略優點缺點建議場景
資料庫存 BLOB事務一致性、備份簡單、權限控管容易資料庫膨脹、備份慢、讀取效能較差小文件、強一致性需求、文件少
資料庫存路徑,文件存檔案系統/物件儲存資料庫輕量、讀取快、擴展性好需處理分散式一致性、備份複雜大文件、高併發、雲原生架構
混合策略平衡兩者優點邏輯較複雜核心業務文件存 DB,非核心存外部

常見錯誤排查

  • 圖片損壞/無法顯示:確認讀寫時未做字元編碼轉換,必須用二進制流
  • OOM 錯誤:改用流式讀寫,勿用 getBytes() 載入大文件
  • 連線中斷:大文件傳輸時間長,調整資料庫 wait_timeout、net_read_timeout 參數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved