常見的圖片上傳做法是將檔案存放在伺服器,資料庫僅保存路徑。雖然這樣插入速度快、符合 Web 架構特性,但刪除時需額外定位並刪除實體檔案,容易造成資料不一致。本文示範將圖片二進位資料直接寫入資料庫(BLOB 欄位),刪除記錄即同步移除圖片,管理更簡單。但請注意:此法會導致資料庫體積快速增長,請依專案需求評估是否採用。
CREATE TABLE `upload` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(20) NOT NULL,
`data` mediumblob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
<!doctype html>
<html>
<head>
<title>Post-Image</title>
</head>
<body>
<form action="post.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="file"/>
<input type="submit" value="OK"/>
</form>
</body>
</html>
<?php
if ($_FILES["file"]["error"] > 0) {
echo "Error: " . $_FILES["file"]["error"] . "<br />";
} else {
$type = $_FILES["file"]["type"];
$size = $_FILES['file']['size'];
$tmp = $_FILES["file"]["tmp_name"];
$fp = fopen($tmp, 'rb');
$data = bin2hex(fread($fp, $size));
$dsn = 'mysql:host=localhost;dbname=test';
echo '<pre>';
try {
$pdo = new PDO($dsn, 'root', 'root');
$pdo->exec("INSERT INTO `upload`(`type`,`data`) VALUES ('$type', 0x$data)");
$id = $pdo->lastInsertId();
echo 'upload success!<a href="view.php?id='.$id.'">View</a>';
$pdo = null;
} catch (PDOException $e) {
echo $e->getMessage();
}
echo '</pre>';
fclose($fp);
}
?>
<?php
$id = $_GET['id'];
if (is_numeric($id)) {
$dsn = 'mysql:host=localhost;dbname=test';
try {
$pdo = new PDO($dsn, 'root', 'root');
$rs = $pdo->query('SELECT * FROM `upload` WHERE `id`='.$id);
$row = $rs->fetchAll();
$data = $row[0];
header("Content-Type: {$data['type']}");
echo $data['data'];
$pdo = null;
} catch (PDOException $e) {
echo $e->getMessage();
}
} else {
exit();
}
?>
建議:小型專案、圖片數量可控、需強一致性時可採用;大型系統建議採用物件儲存(如 S3)或檔案系統+資料庫路徑的混合架構。