Apache httpd + php实现图片缩略图访问

时间:2022-01-14 16:53:13

Apache httpd + php + imagic 实现图片缩略图访问

环境:CentOS7, Apache httpd 2.4, php 5.4.16

实现思路

利用httpd的重写规则把特殊的URL访问映射到PHP脚本,实现缩略图的返回。PHP利用ImageMagic组件实现缩略图文件生成。
需要用到的东西较多,而且需要安装不少东西。下文将详细介绍具体操作,以节省您的时间,告诉请出门左拐。

实现需要的组件安装

yum install -y httpd
yum install -y httpd-devel apr apr-devel libtool
yum install php
yum install -y php-devel
yum install -y php-pear
yum install -y ImageMagick
yum install -y ImageMagick-devel
pecl install imagick

添加extension=imagick.so到/etc/php.d/imagemgick.ini(需要新建)
由于pecl实际需要编译源代码,所以需要安装开发包,如果没有gcc,需要用yum install -y gcc 安装。

缩放实现

通过Apache httpd的Rewrite重写规则实现URL重定向。

RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^/(.+\.(jpg|jpeg|png|bmp)@[-|\d]+x[-|\d]+).*$ /resize.php?file=$1 [L]

上面配置需要加入httpd的配置文件中,我加到了自己位于/etc/httpd/conf.d/xxx.conf文件中。
上面的正则表达式可以依据不同的URL进行修改,含义是:
把以/开始,任意1一个或多个字符开头后跟随”.jpg”, “.jpeg”…并用“@”连接的参数,参数采用“-”或者数字作为宽度,x字符表示乘号(实际为字符x),后面跟随高度。
如果希望得到宽度200像素的图片,可以用”200x-“,如果希望得到200x200的图片(建议不要,以免纵横比失真), 可以用“200x200”,如果希望得到高度限定为200,可以采用”-x200”的方式。
如下:
- http://localhost/test.bmp@200x-
- http://localhost/test.bmp@200x200
- http://localhost/test.bmp@-x200

注意:后面参考文章用的“!”符号作为分隔符在Linux系统中就变成了执行指令了(很危险)

resize.php脚本的实现,可以直接用。

<?php
$ROOT_PATH = "/var/www/html/";

$fileParam = $_REQUEST['file'];

preg_match('/^(.+\.(jpg|jpeg|png|bmp))@([-|\d]+)x([-|\d]+).*$/', $fileParam, $matches);
if ($matches){
$path = $ROOT_PATH.$matches[0];
$srcPath = $ROOT_PATH.$matches[1];
$w = $matches[3];
$h = $matches[4];
$w = preg_match('/^\d+$/i', $w) ? intval($w) : 0;
$h = preg_match('/^\d+$/i', $h) ? intval($h) : 0;
if (file_exists($path) == false){ // 如果缩略图不存在,则创建它
$image = new Imagick($srcPath);
$len = $image->getImageSize();
if($len < 1024 * 50){ // 如果原图小于50k,则不缩放
$path = $srcPath;
}else{
$real_w = $image->getImageWidth();
$real_h = $image->getImageHeight();
// 以下4行代码可以提升性能
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(75); // 设置图片质量
$image->stripImage();
$image->setImageFormat('JPEG');
$image->thumbnailImage($w, $h);
$image->writeImages($path, true);
}
$image->clear();
$image->destroy();
}
@header("Content-Type:image/png");
echo file_get_contents($path);

}else{
echo "Error file parameter.";
}
?>

由于/var/www/html目录是root用户的,所以为了实现缩略图生成,需要该目录可以写入,需要设置如下:
- 修改该目录为其他用户可写

chmod -R o+w /var/www/html
  • 修改该目录的SELinux角色为httpd_sys_rw_content_t
chcon -R -t httpd_sys_rw_content_t   /var/www/html

httpd_sys_rw_content_t httpd_sys_content_t public_content_rw_t 这三个的区别在哪儿呢?
httpd_sys_content_t Read-only directories and files used by Apache
httpd_sys_rw_content_t Readable and writable directories and files used by Apache. Assign this to directories where files can be created or modified by your application, or assign it to files directory to allow your application to modify them.
按我的理解,如果httpd是访问系统目录,那么需要httpd_sys_*_t的策略,如果是普通目录,可以采用public_content_*_t, 读写需要rw.

参考文章:Nginx/Apache图片缩略图技术