插件窝 干货文章 Nginx怎么配合php实现生成实时缩略图功能

Nginx怎么配合php实现生成实时缩略图功能

thumb image Cache Nginx 739    来源:    2025-04-25

Nginx配合PHP实现实时缩略图功能

实时缩略图功能可以通过Nginx和PHP的配合高效实现。以下是完整的解决方案:

方案一:使用Nginx的image_filter模块(推荐)

如果您的Nginx编译时包含了--with-http_image_filter_module,这是最高效的方案。

  1. Nginx配置
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;
    }
}

方案二:PHP处理缩略图生成

如果无法使用image_filter模块,可以使用PHP处理:

  1. Nginx配置
server {
    # ... 其他配置 ...

    location ~ ^/thumb/(\d+)x(\d+)/(.+)$ {
        try_files $uri /thumb.php?width=$1&height=$2&path=$3;
    }
}
  1. thumb.php文件
<?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缓存:

  1. 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/;
    }
}
  1. 修改thumb.php

在输出图像前添加缓存保存逻辑:

// ... 之前的代码 ...

// 保存到缓存
$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;
}

// ... 输出图像的代码 ...

性能优化建议

  1. 使用CDN:将生成的缩略图推送到CDN
  2. 浏览器缓存:设置适当的Cache-Control头
  3. 限制尺寸:防止恶意请求过大尺寸
  4. 安全验证:检查请求的图片路径是否在允许的目录内
  5. 使用opcache:如果使用PHP方案,确保启用OPcache

以上方案可以根据您的具体需求和环境选择最适合的实现方式。