將圖片轉為二進制(BLOB)儲存於資料庫,優點是資料完整性高、備份方便、避免檔案系統權限問題;缺點是資料庫體積膨脹、查詢效能較差、不利 CDN 分發。適用於小型圖片、需強一致性的場景(如用戶頭像、驗證碼、簽名檔)。
<form action="insertPic.php" method="post" enctype="multipart/form-data">
<input type="file" name="myFile" accept="image/*" />
<input type="submit" name="Submit" value="上傳" />
</form>
<?php
// insertPic.php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['myFile'])) {
$file = $_FILES['myFile'];
// 驗證上傳錯誤
if ($file['error'] !== UPLOAD_ERR_OK) {
die("上傳失敗,錯誤代碼:{$file['error']}");
}
// 驗證檔案類型(安全性)
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mimeType, $allowedTypes)) {
die("不支援的檔案類型:{$mimeType}");
}
// 讀取二進制內容
$binaryData = file_get_contents($file['tmp_name']);
// 使用 PDO 預處理語句防止 SQL 注入
try {
$pdo = new PDO("mysql:host=localhost;port=3306;dbname=test", "root", "123456");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare("INSERT INTO img (images, mime_type, file_size, created_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$binaryData, $mimeType, $file['size']]);
echo "資料已插入,ID: " . $pdo->lastInsertId();
} catch (PDOException $e) {
echo "資料庫錯誤:" . $e->getMessage();
}
}
?>
<?php
// show.php
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) die("無效 ID");
try {
$pdo = new PDO("mysql:host=localhost;port=3306;dbname=test", "root", "123456");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare("SELECT images, mime_type FROM img WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
header("Content-Type: " . $row['mime_type']);
header("Content-Length: " . strlen($row['images']));
echo $row['images'];
} else {
http_response_code(404);
echo "圖片不存在";
}
} catch (PDOException $e) {
http_response_code(500);
echo "伺服器錯誤";
}
?>
<img src="show.php?id=5" alt="資料庫圖片" />
| 模式 | 說明 |
|---|---|
| r | 唯讀,指標指向開頭 |
| r+ | 讀寫,指標指向開頭 |
| w | 寫入,截斷為零長度,不存在則建立 |
| w+ | 讀寫,截斷為零長度,不存在則建立 |
| a | 附加,指標指向結尾,不存在則建立 |
| a+ | 讀寫附加,指標指向結尾 |
| b | 二進制模式(Windows 必須,Unix 可省略) |
為單引號、雙引號、反斜線、NULL 字元加上反斜線。注意:使用 PDO 預處理語句時不需要手動呼叫此函數,預處理會自動處理參數跳脫。
string fread(resource $handle, int $length)
從檔案指標讀取最多 length 位元組,遇到 EOF 或網路流封包可用時停止。適用於二進制檔案讀取。
<?php
$newFilePath = 'output.jpg';
$data = $GLOBALS['HTTP_RAW_POST_DATA'] ?? file_get_contents("php://input");
if (empty($data)) {
die("無資料輸入");
}
$fp = fopen($newFilePath, "wb");
fwrite($fp, $data);
fclose($fp);
echo "圖片已儲存至 {$newFilePath}";
<?php
function detectFileType($binaryContent) {
$header = substr($binaryContent, 0, 2);
$unpacked = unpack("C2chars", $header);
$typeCode = intval($unpacked['chars1'] . $unpacked['chars2']);
$typeMap = [
255216 => 'jpg', // FF D8
7173 => 'gif', // 47 49
6677 => 'bmp', // 42 4D
13780 => 'png', // 89 50
7790 => 'exe', // 4D 5A
7784 => 'midi', // 4D 54
8297 => 'rar', // 52 61
];
return $typeMap[$typeCode] ?? 'unknown';
}
// 使用範例
$content = file_get_contents('test.jpg');
echo detectFileType($content); // 輸出: jpg
upload_max_filesize、post_max_size、資料庫 max_allowed_packetfinfo 驗證實際內容,不要信任瀏覽器提供的 $_FILES['type']LONGBLOB(4GB)而非 BLOB(64KB)掌握圖片二進制轉換與儲存技術,能靈活應對各類圖片管理需求,但務必權衡資料庫負載與維護成本,選擇最適合專案的儲存策略。