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

PHP 圖片二進制轉換與資料庫儲存完整實作指南

     編輯:PHP 綜合知識

核心概念:為什麼要將圖片轉為二進制儲存?

將圖片轉為二進制(BLOB)儲存於資料庫,優點是資料完整性高、備份方便、避免檔案系統權限問題;缺點是資料庫體積膨脹、查詢效能較差、不利 CDN 分發。適用於小型圖片、需強一致性的場景(如用戶頭像、驗證碼、簽名檔)。

完整實作流程

1. 前端上傳表單(HTML)

<form action="insertPic.php" method="post" enctype="multipart/form-data">
    <input type="file" name="myFile" accept="image/*" />
    <input type="submit" name="Submit" value="上傳" />
</form>

2. 後端接收並儲存至資料庫

<?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();
    }
}
?>

3. 讀取並輸出圖片

<?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 "伺服器錯誤";
}
?>

4. 前端引用方式

<img src="show.php?id=5" alt="資料庫圖片" />

關鍵函數深度解析

fopen() - 開啟檔案/URL

模式說明
r唯讀,指標指向開頭
r+讀寫,指標指向開頭
w寫入,截斷為零長度,不存在則建立
w+讀寫,截斷為零長度,不存在則建立
a附加,指標指向結尾,不存在則建立
a+讀寫附加,指標指向結尾
b二進制模式(Windows 必須,Unix 可省略)

addslashes() - 字串跳脫

為單引號、雙引號、反斜線、NULL 字元加上反斜線。注意:使用 PDO 預處理語句時不需要手動呼叫此函數,預處理會自動處理參數跳脫。

fread() - 讀取指定長度

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_packet
  • MIME 驗證:務必使用 finfo 驗證實際內容,不要信任瀏覽器提供的 $_FILES['type']
  • 資料庫欄位型別:使用 LONGBLOB(4GB)而非 BLOB(64KB)
  • 考慮混合儲存:大圖存檔案系統(或物件儲存 S3),資料庫只存路徑;小圖才存 BLOB
  • 非同步處理:大量上傳時使用隊列異步處理,避免阻塞請求

掌握圖片二進制轉換與儲存技術,能靈活應對各類圖片管理需求,但務必權衡資料庫負載與維護成本,選擇最適合專案的儲存策略。

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