首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Java 寫入 MySQL BLOB 二進制文件:PreparedStatement 流式寫入、max_allowed_packet 調優、完整讀寫代碼

     編輯:MySQL 資料庫相關知識

JDBC 存取 MySQL BLOB/MEDIUMBLOB/LONGBLOB,核心用 PreparedStatement.setBinaryStream() 流式傳輸,避免全量入內存;讀取用 ResultSet.getBlob() + getBytes()。

表結構與類型選擇

類型最大長度適用場景
TINYBLOB255 B極小圖標
BLOB64 KB縮略圖
MEDIUMBLOB16 MB普通圖片/文檔
LONGBLOB4 GB大文件/視頻

寫入代碼


public void saveBinary(String filePath, Connection conn) throws Exception {
    File file = new File(filePath);
    try (InputStream is = new FileInputStream(file);
         PreparedStatement ps = conn.prepareStatement(
             "INSERT INTO bank_voice(name, data) VALUES (?, ?)")) {
        ps.setString(1, file.getName());
        ps.setBinaryStream(2, is, (int) file.length());  // 流式,無需 byte[]
        ps.executeUpdate();
    }
}

讀取代碼


public void getBinary(String name, String destPath, Connection conn) throws Exception {
    try (PreparedStatement ps = conn.prepareStatement("SELECT data FROM bank_voice WHERE name=?");
         FileOutputStream fos = new FileOutputStream(destPath)) {
        ps.setString(1, name);
        try (ResultSet rs = ps.executeQuery()) {
            if (rs.next()) {
                Blob blob = rs.getBlob("data");
                fos.write(blob.getBytes(1, (int) blob.length()));
            }
        }
    }
}

必改配置:max_allowed_packet


# my.ini / my.cnf
[mysqld]
max_allowed_packet = 16M  # 或 64M/256M,≥ 最大文件

修改後 net stop mysql && net start mysql(Windows)或 systemctl restart mysqld(Linux)。

連接字符串同步:jdbc:mysql://localhost:3306/db?maxAllowedPacket=16777216。

常見異常與解決

異常原因解決
PacketTooBigException文件 > max_allowed_packet調大配置並重啟
OutOfMemoryError用 byte[] 全量讀取大文件改用 setBinaryStream 流式
Communications link failure傳輸超時調大 net_write_timeout/net_read_timeout

下載工具類(輔助)


public static File downLoadFile(String urlStr) throws Exception {
    URL url = new URL(urlStr);
    try (InputStream is = url.openStream();
         FileOutputStream fos = new FileOutputStream("D:/temp.bin")) {
        byte[] buf = new byte[8192];
        int len;
        while ((len = is.read(buf)) != -1) fos.write(buf, 0, len);
        return new File("D:/temp.bin");
    }
}

最佳實踐

  1. 生產環境**不建議**直接存大文件入庫,改用對象存儲(MinIO/S3)+ 數據庫存元數據(路徑、MD5、大小、業務 ID)。
  2. 若必須入庫:表專庫、啟用 innodb_file_per_table、定期 OPTIMIZE TABLE 整理碎片。
  3. 連接池 maxLifetime 設短(30min),防止長連接持有大 Blob 導致內存壓力。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved