利用 LONGTEXT(最大 4GB)配合 mysql_real_escape_string 轉義,可將任意二進制文件作為文本存入 MySQL。實測 650MB ISO 文件寫入/讀出完好,關鍵在調大 max_allowed_packet 並分塊處理內存。
[mysqld]
max_allowed_packet = 1024M -- 必須 ≥ 文件大小
重啟 MySQL 生效。
CREATE DATABASE www;
USE www;
CREATE TABLE www (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
file LONGTEXT
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
stat() 取文件大小 → malloc(size+1) 分配緩衝區。fread() 讀入內存(大文件建議分塊讀取/寫入,避免 OOM)。mysql_real_escape_string() 轉義二進制內容(NUL、換行、引號、Control-Z 等)。INSERT ... VALUES(NULL, 'name', 'escaped_data'),長度 2*size+256。mysql_real_query() 執行寫入。SELECT file FROM www WHERE id=1,用 mysql_fetch_lengths() 取真實長度,fwrite() 還原文件。strcpy(sql, "INSERT INTO www(id,name,file) VALUES(NULL,'peter',");
end = sql + strlen(sql);
*end++ = '\'';
end += mysql_real_escape_string(conn, end, buf, n); // n=文件字節數
*end++ = '\'';
*end++ = ')';
mysql_real_query(conn, sql, end-sql);
sql 需 2*n 空間,650MB 文件需 ~1.3GB 內存;生產環境請改用 mysql_stmt_send_long_data 分片傳輸(見下篇 LONGBLOB 方案)。Packet too large。gbk/latin1 均可,關鍵是轉義與還原成對;若用 utf8mb4 需確保轉義函數支持。autocommit,寫完後 COMMIT,減少 Redo Log 刷盤壓力。小文件(<50MB)、低併發、不想引入對象存儲的簡易業務;大文件/高併發請上 MinIO/S3 + 數據庫存元數據架構。