PHP 直接輸出圖片(如縮圖、水印)時,若無快取機制,CDN 會每次回源,造成後端壓力。解決方式:輸出 ETag(內容雜湊)與 Last-Modified,檢查請求標頭 If-None-Match / If-Modified-Since,相符則回傳 304 Not Modified,瀏覽器/CDN 直接使用快取。
<?php
// 假設 $imageData 為二進位圖片資料(或檔案路徑)
$etag = md5($imageData); // 內容指紋
$lastMod = gmdate('D, d M Y H:i:s', strtotime('2011-01-01')) . ' GMT'; // 固定或依檔案 mtime
// 檢查 ETag
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$clientETag = trim($_SERVER['HTTP_IF_NONE_MATCH'], '"');
if ($clientETag === $etag) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
// 選擇性檢查 Last-Modified
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$clientTime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
$serverTime = strtotime($lastMod);
if ($clientTime >= $serverTime) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
// 輸出快取標頭
header('ETag: "' . $etag . '"');
header('Last-Modified: ' . $lastMod);
header('Cache-Control: max-age=2592000, public'); // 30 天
header('Content-Type: image/jpeg'); // 依實際格式調整
echo $imageData;
?>
md5() 或 sha1(),確保內容變更時 ETag 改變。若圖片為動態生成(如帶參數縮圖),需包含所有參數計算雜湊。If-None-Match 放入 $_SERVER,無需額外 FastCGI 參數設定。filemtime() 或固定版本日期。若動態生成無實體檔,建議用 ETag 為主。max-age 秒數 + public 允許 CDN 快取。exit。location /image.php {
fastcgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
fastcgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;
# 其他 fastcgi_param...
}
現代 Nginx 預設已將所有 HTTP 標頭對應至 $_SERVER['HTTP_*'],通常無需額外設定。