首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 將圖片儲存至 MySQL 資料庫實作教學

     編輯:PHP 相關知識

PHP 將圖片存入 MySQL 資料庫完整指南

雖然生產環境通常建議將圖片存放檔案系統或雲端儲存 (僅存路徑於資料庫),但特定場景 (如小型應用、資料完整性要求高、避免檔案散落) 下將圖片以 BLOB 型別直接存入資料庫仍有其價值。本文提供完整實作範例。

資料表結構設計

CREATE TABLE IF NOT EXISTS `images` (
  `id` INT(8) NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(150) DEFAULT NULL,
  `content` LONGBLOB NOT NULL,
  `mime_type` VARCHAR(50) NOT NULL,
  `file_size` INT UNSIGNED NOT NULL,
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

關鍵欄位說明:

  • LONGBLOB:支援最大 4GB 二進位資料 (MEDIUMBLOB 16MB, BLOB 64KB)
  • mime_type:儲存 MIME 類型 (image/jpeg, image/png, image/gif 等),輸出時設定正確 Content-Type
  • file_size:儲存檔案大小,便於前端顯示或限制

圖片上傳與存入資料庫

<?php
// 資料庫連線 (建議使用 PDO)
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', 'root', [
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
  $file = $_FILES['image'];
  
  // 基本驗證
  $allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
  $max_size = 5 * 1024 * 1024; // 5MB
  
  if (!in_array($file['type'], $allowed_types)) {
    die('不支援的檔案類型');
  }
  if ($file['size'] > $max_size) {
    die('檔案過大,限制 5MB');
  }
  if ($file['error'] !== UPLOAD_ERR_OK) {
    die('上傳失敗,錯誤代碼: ' . $file['error']);
  }
  
  // 讀取檔案內容
  $image_data = file_get_contents($file['tmp_name']);
  if ($image_data === false) {
    die('無法讀取檔案');
  }
  
  // 寫入資料庫 (使用預處理語句,避免 SQL 注入)
  $sql = "INSERT INTO images (title, content, mime_type, file_size) VALUES (?, ?, ?, ?)";
  $stmt = $pdo->prepare($sql);
  $stmt->execute([
    $file['name'],
    $image_data,
    $file['type'],
    $file['size']
  ]);
  
  echo "圖片上傳成功,ID: " . $pdo->lastInsertId();
}

?>

<!DOCTYPE html>
<html>
<body>
<form method="post" enctype="multipart/form-data">
  <input type="file" name="image" accept="image/*" required>
  <button type="submit">上傳至資料庫</button>
</form>
</body>
</html>

從資料庫讀取並輸出圖片

<?php
// image.php?id=123
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', 'root');

$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
  http_response_code(400);
  die('無效 ID');
}

$stmt = $pdo->prepare("SELECT content, mime_type FROM images WHERE id = ?");
$stmt->execute([$id]);
$image = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$image) {
  http_response_code(404);
  die('圖片不存在');
}

// 輸出正確的 HTTP 標頭
header('Content-Type: ' . $image['mime_type']);
header('Content-Length: ' . strlen($image['content']));
header('Cache-Control: public, max-age=31536000'); // 快取一年
header('ETag: "' . md5($image['content']) . '"');

// 輸出二進位資料
echo $image['content'];
?>

前端引用方式

<img src="image.php?id=123" alt="資料庫圖片">
<!-- 或作為 CSS 背景 -->
<div style="background-image: url(image.php?id=123); width: 200px; height: 200px;"></div>

效能與架構考量

優點缺點
資料完整性:圖片與資料庫記錄原子性一致資料庫體積暴增:備份/還原/複製耗時大幅增加
部署簡單:單一資料庫檔案即可遷移記憶體壓力:PHP 處理大圖片需載入記憶體
權限控管:透過資料庫權限管理存取無法利用 CDN/靜態檔案伺服器加速
交易支援:圖片與相關資料同步提交/回滾複雜查詢效能:SELECT * 會載入大量 BLOB 資料

最佳實踐建議

  1. 分離查詢:列表頁只查 id, title, mime_type, file_size,不查 content
  2. 限制檔案大小:建議 < 1MB,大檔案改用檔案系統或物件儲存
  3. 啟用快取:輸出時設定 ETag、Cache-Control、Expires
  4. 考慮混合方案:縮圖存資料庫,原圖存檔案系統/雲端
  5. 監控資料庫大小:設定告警閾值,定期清理無用圖片

現代化替代方案

  • 本地檔案系統:存儲路徑於資料庫,配合 Nginx/Apache 直接服務靜態檔案
  • 雲端物件儲存:AWS S3、阿里云 OSS、騰訊云 COS、Google Cloud Storage
  • 分散式檔案系統:MinIO、FastDFS、Ceph、GlusterFS
  • Base64 編碼存文字欄位:極小圖片 (如 favicon、圖示) 可考慮,但體積增大 33%
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved