將圖片、文件等二進位資料直接存入 MySQL 資料庫,雖非主流架構(通常建議存檔案路徑),但在特定需求下(如資料完整性、備份簡化、跨伺服器同步)仍具優勢。本文示範建立資料表、上傳儲存、讀取輸出的完整流程。
CREATE DATABASE binary_data;
USE binary_data;
CREATE TABLE `binary_data` (
`id` INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`description` CHAR(50),
`bin_data` LONGBLOB,
`filename` CHAR(50),
`filesize` CHAR(50),
`filetype` CHAR(50)
);
LONGBLOB 可儲存最多 4GB 二進位資料,適合圖片、PDF 等檔案。<?php
// store.php
if (isset($_POST['submit'])) {
// 連線資料庫(請修改為實際帳密)
$conn = mysqli_connect("localhost", "root", "password", "binary_data");
if (!$conn) die("連線失敗: " . mysqli_connect_error());
// 取得上傳檔案資訊
$tmpName = $_FILES['form_data']['tmp_name'];
$name = $_FILES['form_data']['name'];
$size = $_FILES['form_data']['size'];
$type = $_FILES['form_data']['type'];
$desc = mysqli_real_escape_string($conn, $_POST['form_description']);
// 讀取二進位內容並逃脫
$fp = fopen($tmpName, 'r');
$content = fread($fp, $size);
fclose($fp);
$data = mysqli_real_escape_string($conn, $content);
// 寫入資料庫
$sql = "INSERT INTO binary_data (description, bin_data, filename, filesize, filetype)
VALUES ('$desc', '$data', '$name', '$size', '$type')";
if (mysqli_query($conn, $sql)) {
$id = mysqli_insert_id($conn);
echo "檔案已儲存,資料庫 ID: $id";
} else {
echo "錯誤: " . mysqli_error($conn);
}
mysqli_close($conn);
} else {
?>
<?php } ?>
關鍵點:
enctype="multipart/form-data"。$_FILES 取得暫存檔路徑、原始檔名、大小、型別。mysqli_real_escape_string() 防止二進位資料中的特殊字元破壞 SQL。mysqli_insert_id() 即為該筆記錄的主鍵 ID,前端可記錄以便後續讀取。<?php
// getdata.php?id=2
if (isset($_GET['id'])) {
$id = (int)$_GET['id']; // 強制轉整數防注入
$conn = mysqli_connect("localhost", "root", "password", "binary_data");
if (!$conn) die("連線失敗");
$sql = "SELECT bin_data, filetype FROM binary_data WHERE id = $id";
$result = mysqli_query($conn, $sql);
if ($row = mysqli_fetch_assoc($result)) {
header("Content-Type: " . $row['filetype']);
echo $row['bin_data'];
} else {
header("HTTP/1.0 404 Not Found");
echo "找不到指定檔案";
}
mysqli_close($conn);
} else {
echo "請提供 id 參數";
}
?>
使用方式:
getdata.php?id=3 即可顯示圖片。<img src="getdata.php?id=3">。預設 PHP、MySQL 限制上傳與封包大小,需調整下列參數(以 24MB 為例):
| 層面 | 設定項目 | 建議值 |
|---|---|---|
| HTML 表單 | <input type="hidden" name="MAX_FILE_SIZE" value="24000000"> | 24000000 |
| PHP (php.ini) | upload_max_filesize | 24M |
| PHP (php.ini) | post_max_size | 24M |
| PHP (php.ini) | max_execution_time | 0 (無限制) 或較大秒數 |
| MySQL 啟動參數 | max_allowed_packet | 24M |
| MySQL 設定檔 (my.cnf/my.ini) | [mysqld] max_allowed_packet=24M | 24M |
修改 my.cnf 後需重啟 MySQL 服務生效。若仍失敗,請檢查錯誤日誌確認是否為記憶體或逾時問題。
mysqli_prepare / PDO)取代字串拼接。$_FILES['type'],建議搭配 finfo_file() 檢測真實 MIME。getdata.php 加入 ETag、Last-Modified、Cache-Control 標頭,減少重複傳輸。掌握上述流程,即可在 PHP 專案中靈活處理二進位檔案的資料庫儲存與讀取。實務上請根據專案規模與維運考量,權衡「存 DB」與「存檔案系統」的優劣。