首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 儲存圖片/檔案實戰:BLOB 欄位完整操作指南 (PHP 範例)

     編輯:MySQL 資料庫相關知識

前言:為什麼要把檔案存進資料庫?

雖然「檔案存檔案系統、資料庫存路徑」是主流架構,但特定場景下直接存入 BLOB 有優勢:交易一致性 (檔案與資料同進同出)、備份原子性 (單一 dump 即完整)、權限控管 (透過 SQL GRANT 管控存取)。本文示範完整流程:建表、上傳 (store.php)、讀取顯示 (getdata.php)、大檔案調校。

1. 建立資料庫與資料表

CREATE DATABASE binary_data CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE binary_data;

CREATE TABLE binary_data (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    description VARCHAR(255) NOT NULL DEFAULT '',
    bin_data LONGBLOB NOT NULL,
    filename VARCHAR(255) NOT NULL DEFAULT '',
    filesize BIGINT UNSIGNED NOT NULL DEFAULT 0,
    filetype VARCHAR(100) NOT NULL DEFAULT '',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

關鍵點:LONGBLOB 最大 4GB;filesize 用 BIGINT 防溢位;加上 created_at 利稽核。

2. 上傳存檔 — store.php (現代化 PDO 版)

<?php
// store.php
require_once 'db_config.php'; // 含 PDO 連線設定

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['form_data'])) {
    $file = $_FILES['form_data'];
    $desc = trim($_POST['form_description'] ?? '');
    
    // 基本驗證
    if ($file['error'] !== UPLOAD_ERR_OK) {
        die('上傳失敗,錯誤碼: ' . $file['error']);
    }
    if ($file['size'] > 24 * 1024 * 1024) { // 24MB 上限
        die('檔案超過 24MB 限制');
    }
    
    $pdo = getPDO(); // 回傳 PDO 實例
    $pdo->beginTransaction();
    try {
        $stmt = $pdo->prepare(
            "INSERT INTO binary_data (description, bin_data, filename, filesize, filetype) 
             VALUES (?, ?, ?, ?, ?)"
        );
        $stmt->bindValue(1, $desc, PDO::PARAM_STR);
        $stmt->bindValue(2, file_get_contents($file['tmp_name']), PDO::PARAM_LOB);
        $stmt->bindValue(3, $file['name'], PDO::PARAM_STR);
        $stmt->bindValue(4, $file['size'], PDO::PARAM_INT);
        $stmt->bindValue(5, $file['type'], PDO::PARAM_STR);
        $stmt->execute();
        $id = $pdo->lastInsertId();
        $pdo->commit();
        echo "

檔案已儲存,資料庫 ID: $id

"; } catch (Exception $e) { $pdo->rollBack(); die('資料庫錯誤: ' . $e->getMessage()); } } else { ?> 上傳檔案到 MySQL
檔案描述:
選擇檔案:

3. 讀取顯示 — getdata.php

<?php
// getdata.php?id=123
require_once 'db_config.php';

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if (!$id) { http_response_code(400); die('Invalid ID'); }

$pdo = getPDO();
$stmt = $pdo->prepare("SELECT bin_data, filetype FROM binary_data WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$row) { http_response_code(404); die('Not Found'); }

header('Content-Type: ' . $row['filetype']);
header('Content-Length: ' . strlen($row['bin_data']));
// 可選:強制下載而非瀏覽器內嵌
// header('Content-Disposition: attachment; filename="download"');
echo $row['bin_data'];

4. 前端引用範例

<!-- 直接當圖片來源 -->
<img src="getdata.php?id=3" alt="從資料庫讀取的圖片">

<!-- 提供下載連結 -->
<a href="getdata.php?id=5" download>下載檔案</a>

5. 突破 1MB/24MB 限制 — 關鍵配置調整

層面設定項目建議值 (24MB 範例)位置
HTML 表單MAX_FILE_SIZE25165824store.php hidden input
PHPupload_max_filesize24Mphp.ini
PHPpost_max_size25M (略大於 upload_max)php.ini
PHPmemory_limit64M+ (需 > post_max_size)php.ini
MySQLmax_allowed_packet32M (略大於最大檔案)my.cnf [mysqld] 區段
MySQLinnodb_log_file_size256M+ (大交易需較大 redo log)my.cnf [mysqld] 區段

重啟生效:修改 php.ini 需重啟 php-fpm/apache;修改 my.cnf 需重啟 mysqld。

6. 效能與架構建議

  • 小檔案 (< 1MB):資料庫存儲可接受
  • 中大檔案:強烈建議**物件儲存 (S3/MinIO) + 資料庫存 URL**,資料庫僅存中繼資料
  • 若必須存大檔案於 DB:啟用 innodb_file_per_table、考慮壓縮 (COMPRESSED 行格式)、分離檔案表到獨立表空間
  • 讀取端加上 ETag/Last-Modified、CDN 快取、Range 請求支援

總結

MySQL BLOB 存檔技術成熟,但架構決策應基於檔案大小、存取模式、擴展性需求。小型專案、強一致性需求可直接用;中大型系統請採用「資料庫存元資料、物件儲存存內容」的混合架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved