实时缩略图功能可以通过Nginx和PHP的配合高效实现。以下是完整的解决方案:
如果您的Nginx编译时包含了--with-http_image_filter_module
,这是最高效的方案。
server {
# ... 其他配置 ...
# 缩略图URL规则:/thumb/<width>x<height>/path/to/image.jpg
location ~ ^/thumb/(\d+)x(\d+)/(.+)$ {
set $width $1;
set $height $2;
set $image_path $3;
# 检查原图是否存在
if (!-f $document_root/$image_path) {
return 404;
}
# 使用image_filter生成缩略图
image_filter resize $width $height;
image_filter_jpeg_quality 85;
image_filter_buffer 10M;
# 设置缓存头
expires 30d;
add_header Cache-Control "public";
# 传递原图路径
rewrite ^ /$image_path break;
}
}
如果无法使用image_filter模块,可以使用PHP处理:
server {
# ... 其他配置 ...
location ~ ^/thumb/(\d+)x(\d+)/(.+)$ {
try_files $uri /thumb.php?width=$1&height=$2&path=$3;
}
}
<?php
// 获取参数
$width = (int)$_GET['width'];
$height = (int)$_GET['height'];
$imagePath = $_GET['path'];
// 验证参数
if ($width <= 0 || $height <= 0 || !file_exists($imagePath)) {
header('HTTP/1.1 404 Not Found');
exit;
}
// 获取图片信息
$imageInfo = getimagesize($imagePath);
$mimeType = $imageInfo['mime'];
// 根据不同类型创建图像资源
switch ($mimeType) {
case 'image/jpeg':
$source = imagecreatefromjpeg($imagePath);
break;
case 'image/png':
$source = imagecreatefrompng($imagePath);
break;
case 'image/gif':
$source = imagecreatefromgif($imagePath);
break;
default:
header('HTTP/1.1 400 Bad Request');
exit;
}
// 创建缩略图
$thumb = imagecreatetruecolor($width, $height);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $width, $height, $imageInfo[0], $imageInfo[1]);
// 输出图像
header('Content-Type: ' . $mimeType);
header('Cache-Control: public, max-age=2592000'); // 30天缓存
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT');
switch ($mimeType) {
case 'image/jpeg':
imagejpeg($thumb, null, 85);
break;
case 'image/png':
imagepng($thumb);
break;
case 'image/gif':
imagegif($thumb);
break;
}
// 释放内存
imagedestroy($source);
imagedestroy($thumb);
为了提高性能,可以结合Nginx缓存:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=thumbnail_cache:10m inactive=30d use_temp_path=off;
server {
# ... 其他配置 ...
location ~ ^/thumb/(\d+)x(\d+)/(.+)$ {
proxy_cache thumbnail_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 30d;
add_header X-Cache-Status $upstream_cache_status;
# 如果缓存不存在,转发给PHP处理
if (!-f "/var/cache/nginx/thumb/$1x$2/$3") {
rewrite ^ /thumb.php?width=$1&height=$2&path=$3 break;
}
# 直接返回缓存文件
rewrite ^ /cache/thumb/$1x$2/$3 break;
}
location /cache/ {
internal;
alias /var/cache/nginx/;
}
}
在输出图像前添加缓存保存逻辑:
// ... 之前的代码 ...
// 保存到缓存
$cacheDir = '/var/cache/nginx/thumb/' . $width . 'x' . $height . '/' . dirname($imagePath);
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
$cacheFile = $cacheDir . '/' . basename($imagePath);
switch ($mimeType) {
case 'image/jpeg':
imagejpeg($thumb, $cacheFile, 85);
break;
case 'image/png':
imagepng($thumb, $cacheFile);
break;
case 'image/gif':
imagegif($thumb, $cacheFile);
break;
}
// ... 输出图像的代码 ...
以上方案可以根据您的具体需求和环境选择最适合的实现方式。