在伺服器端完成圖片縮放比瀏覽器端縮放更省頻寬、畫質更穩定。本類別 ImageResizer 封裝縮放邏輯,支援 ETag、Last-Modified、Cache-Control,配合 CDN/瀏覽器快取可大幅降低後端壓力。
<?php
class ImageResizer {
private $sourcePath;
private $mime;
public function __construct(string $sourcePath) {
$this->sourcePath = $sourcePath;
$info = getimagesize($sourcePath);
$this->mime = $info['mime'] ?? 'image/jpeg';
}
public function resize(int $maxW, int $maxH): void {
// 快取檢查
$etag = md5_file($this->sourcePath);
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
header('HTTP/1.1 304 Not Modified');
exit;
}
list($ow, $oh) = getimagesize($this->sourcePath);
$ratio = $ow / $oh;
if ($maxW / $maxH > $ratio) $maxW = $maxH * $ratio;
else $maxH = $maxW / $ratio;
$dst = imagecreatetruecolor($maxW, $maxH);
$src = $this->createSource();
imagecopyresampled($dst, $src, 0,0,0,0, $maxW,$maxH, $ow,$oh);
// 輸出標頭
header('Content-Type: ' . $this->mime);
header('ETag: ' . $etag);
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($this->sourcePath)) . ' GMT');
header('Cache-Control: max-age=2592000, public'); // 30 天
$this->output($dst);
imagedestroy($dst);
imagedestroy($src);
}
private function createSource() {
switch ($this->mime) {
case 'image/gif': return imagecreatefromgif($this->sourcePath);
case 'image/png': return imagecreatefrompng($this->sourcePath);
default: return imagecreatefromjpeg($this->sourcePath);
}
}
private function output($img) {
switch ($this->mime) {
case 'image/gif': imagegif($img); break;
case 'image/png': imagepng($img); break;
default: imagejpeg($img, null, 90);
}
}
}
// 使用範例:image.php?src=photo.jpg&w=300&h=200
if (isset($_GET['src'], $_GET['w'], $_GET['h'])) {
$resizer = new ImageResizer($_GET['src']);
$resizer->resize((int)$_GET['w'], (int)$_GET['h']);
}
?>
<img src="image.php?src=uploads/photo.jpg&w=300&h=200" alt="縮圖" />
md5_file() 確保內容變更即更新快取。exit,節省頻寬。getimagesize() 偵測 MIME,呼叫對應 GD 函式。src 參數路徑(防止目錄遍歷),建議用資料庫 ID 對應實體路徑。