由于一个项目前端加载图片延迟以及流量等问题,我们对图片进行了处理,这里进行一下记录也给需要的老铁一些参考,主要实现图片裁剪压缩缓存。可以指定宽度和高度,这里不指定高度可以进行等比缩放来适应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);
?>