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

PHP 動態生成縮略圖輸出:GD 庫即時縮放、不佔用磁碟空間

     編輯:PHP 相關知識

PHP 動態生成縮略圖輸出:GD 庫即時縮放、不佔用磁碟空間

針對圖片較大、需多種尺寸縮略圖的場景,動態生成可避免預先儲存大量規格檔案。本文實作一個 thumbs.php,透過 URL 參數指定原圖與目標尺寸,即時縮放並直接輸出二進位圖片流。

一、核心實作 thumbs.php

<?php
// 1. 參數驗證與清理
$filename = basename($_GET['filename'] ?? ''); // 防止目錄遍歷
$width    = (int)($_GET['width'] ?? 0);
$height   = (int)($_GET['height'] ?? 0);

if (!$filename || $width <= 0 || $height <= 0) {
    http_response_code(400);
    exit('Invalid parameters');
}

// 2. 原圖路徑 (建議放在 Web 根目錄外)
$baseDir = __DIR__ . '/../images/'; // 實體路徑,不可直接瀏覽
$sourcePath = $baseDir . $filename;

if (!is_file($sourcePath)) {
    http_response_code(404);
    exit('Image not found');
}

// 3. 取得原圖資訊
$info = getimagesize($sourcePath);
if (!$info) {
    http_response_code(500);
    exit('Invalid image file');
}
list($srcW, $srcH, $mime) = $info;

// 僅支援常見格式
$allowedMime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($mime, $allowedMime, true)) {
    http_response_code(415);
    exit('Unsupported image type');
}

// 4. 計算目標尺寸 (保持比例)
if ($width && $height) {
    // 兩者皆指定:縮放填滿,再裁切置中 (或依需求調整)
    $ratio = max($width / $srcW, $height / $srcH);
    $newW = (int)round($srcW * $ratio);
    $newH = (int)round($srcH * $ratio);
} elseif ($width) {
    $ratio = $width / $srcW;
    $newW = $width;
    $newH = (int)round($srcH * $ratio);
} else {
    $ratio = $height / $srcH;
    $newH = $height;
    $newW = (int)round($srcW * $ratio);
}

// 5. 建立真彩畫布並重採樣
$dstImg = imagecreatetruecolor($newW, $newH);

// 保持透明度 (PNG/GIF/WEBP)
if (in_array($mime, ['image/png', 'image/gif', 'image/webp'])) {
    imagealphablending($dstImg, false);
    imagesavealpha($dstImg, true);
    $transparent = imagecolorallocatealpha($dstImg, 255, 255, 255, 127);
    imagefilledrectangle($dstImg, 0, 0, $newW, $newH, $transparent);
}

// 根據 MIME 載入原圖資源
switch ($mime) {
    case 'image/jpeg': $srcImg = imagecreatefromjpeg($sourcePath); break;
    case 'image/png':  $srcImg = imagecreatefrompng($sourcePath); break;
    case 'image/gif':  $srcImg = imagecreatefromgif($sourcePath); break;
    case 'image/webp': $srcImg = imagecreatefromwebp($sourcePath); break;
}

// 重採樣縮放 (高品質)
imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $newW, $newH, $srcW, $srcH);

// 6. 輸出圖片二進位流
header('Content-Type: ' . $mime);
header('Cache-Control: public, max-age=31536000'); // 1 年快取
header('ETag: "' . md5_file($sourcePath) . '"');

switch ($mime) {
    case 'image/jpeg': imagejpeg($dstImg, null, 90); break; // 品質 90
    case 'image/png':  imagepng($dstImg, null, 6); break;  // 壓縮等級 6
    case 'image/gif':  imagegif($dstImg); break;
    case 'image/webp': imagewebp($dstImg, null, 90); break;
}

// 7. 釋放資源
imagedestroy($srcImg);
imagedestroy($dstImg);
?>

二、前端調用方式

<!-- 固定寬度,高度自適應 -->
<img src="/thumbs.php?filename=photo.jpg&width=300" alt="...">

<!-- 固定寬高 (會裁切/拉伸,依計算邏輯) -->
<img src="/thumbs.php?filename=photo.jpg&width=200&height=200" alt="...">

<!-- 響應式圖片 (搭配 srcset) -->
<img src="/thumbs.php?filename=photo.jpg&width=800"
     srcset="/thumbs.php?filename=photo.jpg&width=400 400w,
             /thumbs.php?filename=photo.jpg&width=800 800w,
             /thumbs.php?filename=photo.jpg&width=1200 1200w"
     sizes="(max-width: 600px) 400px, 800px" alt="...">

三、效能優化關鍵點

  1. 快取策略:輸出 ETag、Cache-Control,瀏覽器/CDN 可快取,減少重複生成。
  2. 伺服端快取:生成後存入 /cache/thumbs/{width}x{height}/{filename},下次請求直接 readfile() 或 Nginx try_files 靜態服務。
  3. 限制尺寸:驗證 $width, $height <= 2000,防止惡意請求大圖耗盡記憶體。
  4. 異步預生成:上傳時觸發佇列任務預生成常用規格,動態端僅作為補漏。
  5. 使用 imagick (ImageMagick):若安裝 imagick 擴充,效能與品質優於 GD,支援更多格式 (HEIC, AVIF, TIFF 等)。

四、安全性檢查清單

  • ✅ basename() 防止 ../../etc/passwd 遍歷
  • ✅ 白名單驗證 MIME 類型
  • ✅ 原圖放在 Web 根目錄外
  • ✅ 限制最大輸出像素 (防記憶體耗盡)
  • ✅ 關閉錯誤顯示 ini_set('display_errors', 0),避免洩露路徑資訊

五、Nginx 靜態快取配置範例

location /thumbs.php {
    # 嘗試直接服務已生成的快取檔
    try_files /cache/thumbs$uri =404;

    # 快取不存在時代理到 PHP 生成
    fastcgi_pass php-fpm;
    fastcgi_param SCRIPT_FILENAME $document_root/thumbs.php;
    include fastcgi_params;
}

# 由 PHP 生成快取檔至 /var/www/cache/thumbs/...

動態縮略圖方案靈活高效,配合快取機制可支撐高併發圖片服務。根據流量規模,可漸進式升級為「上傳時預生成 + CDN 分發」架構。

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