Nginx+fastcgi+PHP缩略图缓存服务

由于一个项目前端加载图片延迟以及流量等问题,我们对图片进行了处理,这里进行一下记录也给需要的老铁一些参考,主要实现图片裁剪压缩缓存。可以指定宽度和高度,这里不指定高度可以进行等比缩放来适应app加载图片高度自适应的需要。同时对部分类型的图片进行了区别处理主要是防止png图片透明或者白色背景丢失的问题。当然这里的图片类型还有一些,项目不涉及所以这里就没有处理。
环境准备
安装GD库
./configure --prefix=/usr/local # 可根据需要调整安装路径
make
sudo make install

Nginx 编译
sudo yum install pcre pcre-devel
Openssl 软连接修复
yum install openssl-devel 安装
ln -s /usr/local/ssl .openssl

./configure
–prefix=/usr/local/nginx
–with-http_ssl_module
–with-http_image_filter_module
–sbin-path=/usr/local/nginx/sbin/nginx
–conf-path=/usr/local/nginx/conf/nginx.conf
–error-log-path=/usr/local/nginx/logs/error.log
–http-log-path=/usr/local/nginx/logs/access.log
–pid-path=/usr/local/nginx/run/nginx.pid
–lock-path=/usr/local/nginx/run/nginx.lock
–user=nginx
–group=nginx
Nginx依赖检测
ldd /usr/local/nginx/sbin/nginx

GD库环境变量配置
export LD_LIBRARY_PATH=/usr/local/lib

安装PHP
使用yum(适用于CentOS/RHEL系统)
添加EPEL仓库(对于较旧的CentOS可能需要此步骤以获取最新PHP版本):

Bash
sudo yum install epel-release -y
安装PHP及相关扩展(假设使用PHP 7.4版本):

Bash
sudo yum install php php-common php-opcache php-mbstring php-gd php-json php-xml php-curl php-pdo php-mysqlnd -y
如果你的CentOS版本提供了PHP 8.x,则可以替换为对应版本的包名,例如php80替代php。

或手动编译安装(高级用户)
安装依赖库:

Bash
sudo yum groupinstall “Development Tools” -y
sudo yum install libxml2-devel openssl-devel curl-devel libjpeg-turbo-devel freetype-devel libpng-devel bzip2-devel -y
下载PHP源码包:

Bash
wget https://www.php.net/distributions/php-7.x.x.tar.gz # 替换x.x为实际版本号
tar zxf php-7.x.x.tar.gz
cd php-7.x.x
配置、编译并安装PHP:

Bash
./configure --prefix=/usr/local/php73 --with-config-file-path=/etc/php73 --with-config-file-scan-dir=/etc/php73/conf.d --enable-fpm --with-fpm-user=apache --with-fpm-group=apache --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-mbstring --enable-exif --enable-ftp --with-curl --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-openssl --with-icu-dir --enable-soap --enable-calendar --enable-bcmath --enable-shmop --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --with-iconv --with-zlib
make
sudo make install

nginx配置:

server {
listen 8083;
server_name localhost2;

            root /mnt/nfs; # 图片源目录
            index index.html;

            location ~ ^/thumbnail/(?<filename>.+?)(\.(jpg|jpeg|png|gif))$ {
                    set $width $arg_w;
                    set $height $arg_h;
                    set $x 'x';
                    set $file_path $document_root/$filename.$3;

                    # 检查缓存文件是否存在
                    if (-f $document_root/cache/$width$x$height/$filename.$3) {
                            rewrite ^ /cache/$width$x$height/$filename.$2 break;
                    }


                    error_page 404 = @php_thumbnail;
            }

            location @php_thumbnail {
                    internal;

                    fastcgi_pass 127.0.0.1:9000;
                    fastcgi_param SCRIPT_FILENAME /mnt/image_cache_server/generate_thumbnail.php;
                    fastcgi_param IMAGE_PATH $file_path;
                    fastcgi_param WIDTH $width;
                    fastcgi_param HEIGHT $height;
                    include fastcgi_params;
            }

            location /cache {
                    alias /usr/local/nginx/html/image_cache; # 缩略图缓存目录
                    expires 60d; # 设置缓存过期时间(可按需调整)
            }

    }

PHP-FPM: 图片处理服务示例代码


<?php
$filePath = $_SERVER['IMAGE_PATH'];
$width = (int)$_SERVER['WIDTH'];
$height = (int)$_SERVER['HEIGHT'];

// 检查文件存在性并进行安全检查
if (!file_exists($filePath) || !is_file($filePath)) {
    header('HTTP/1.1 404 Not Found');
    exit();
}

// 使用GD库或Imagick等处理图片库生成缩略图
// 示例使用GD库:
$sourceImage = imagecreatefromstring(file_get_contents($filePath));
$sourceWidth = $sourceWidth = imagesx($sourceImage);
if ($width === null || $width == 0) {
	$width = $sourceWidth;
}
if ($height === null || $height == 0) {
    $height = imagesy($sourceImage)* ($width / $sourceWidth);
}

//$thumbnail = imagecreatetruecolor($width, $height);
//$transparent_color = imagecolorallocatealpha($thumbnail, 0, 0, 0, 127); // 这里创建一个半透明的颜色
//imagecopyresampled($thumbnail, $sourceImage, 0, 0, 0, 0, $width, $height, imagesx($sourceImage), imagesy($sourceImage));


// 保存缩略图至缓存目录
$imageExt = pathinfo($filePath, PATHINFO_EXTENSION);

switch ($imageExt) {
        case 'jpg':
		case 'JPG':
        case 'jpeg':
            $source_image = imagecreatefromjpeg($filePath);
            break;
        case 'png':
            $source_image = imagecreatefrompng($filePath);
            imagesavealpha($source_image, true);
            imagealphablending($source_image, false);
            break;
        case 'gif':
            $source_image = imagecreatefromgif($filePath);
            break;
        default:
            $source_image = imagecreatefromjpeg($filePath);
            break;
    }
$newImage = imagecreatetruecolor($width, $height);
if (in_array($imageExt, ['png', 'gif'])) {
	$transparent_color = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
	imagefilledrectangle($newImage, 0, 0, $new_width, $new_height, $transparent_color);
	imagesavealpha($newImage, true);
	imagealphablending($newImage, false);
}

imagecopyresampled($newImage, $source_image, 0, 0, 0, 0, $width, $height, imagesx($source_image), imagesy($source_image));
 
$cacheDir = '/usr/local/nginx/html/image_cache/'.$width.'x'.$height.'/';
if (!file_exists($cacheDir) && !is_dir($cacheDir)) {
    mkdir($cacheDir, 0755, true); // 第三个参数为true表示递归创建多级目录(如果需要的话)
}
$cachePath = '/usr/local/nginx/html/image_cache/' . $width . 'x' . $height . '/' . basename($filePath);
if (!file_exists($cachePath)) {
    touch($cachePath); // 创建一个空文件
}
   // 根据原图格式保存新尺寸的图片
    switch ($imageExt) {
        case 'jpg':
        case 'jpeg':
            imagejpeg($newImage, $cachePath);
            break;
        case 'png':
            imagepng($newImage, $cachePath, 9); // 使用最高压缩级别
            break;
        case 'gif':
            imagegif($newImage, $cachePath);
            break;
    }
#imagejpeg($thumbnail, $cachePath); // 或者使用对应的函数如imagepng/imagegif保存其他格式

// 输出缩略图到客户端
//header('Content-Type: image/jpeg'); // 根据实际情况设置正确的MIME类型
//readfile($cachePath);
$imageType = exif_imagetype($cachePath); // 获取图片类型

switch ($imageType) {
    case IMAGETYPE_JPEG:
        $mimeType = 'image/jpeg';
        break;
    case IMAGETYPE_PNG:
        $mimeType = 'image/png';
        break;
    case IMAGETYPE_GIF:
        $mimeType = 'image/gif';
        break;
    default:
        // 如果是不支持或未知的图像类型,可以返回一个默认值或者错误信息
        $mimeType = 'image/jpeg';
        break;
}

// 设置HTTP响应头中的Content-Type字段
header('Content-Type: ' . $mimeType);

// 然后输出图片数据(这里假设你已经有了图片数据,比如从文件读取)
readfile($cachePath);

// 清理资源
imagedestroy($sourceImage);
imagedestroy($newImage);
?>
  • 33
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值