PHP加Nginx实现动态裁剪图片方案


Posted in PHP onMarch 10, 2014

许久以前写过一篇也是关于高性能PHP图片动态裁剪方案的文章,那文章使用的是nginx Cache和rewrite实现的,当然再加上CDN,那个方案存在一个问题就是图片并没有实际生成,而是以二进制的形式存在缓存中。如果缓存失效了那么还需要请求php再次生成。如果说到区别这是我暂且认为的吧。
利用空余时间,新增了静态生成图片支持,支持对图片3种模式切换,在门户网站自动对图片尺寸进行裁剪,减少服务器带宽,理论上应该也满足了业务的需求吧,图片裁剪使用了Imagick组件。

一、思路再现:
1、先写好请求服务器生成图片动态脚本,主要就是对图片进行等比缩放计算+裁剪。
2、确定你想要生成的url规则,比如http://www.domain.com/www/300×200-1/test.jpg。
3、对浏览器做缓存处理。
4、结束。
二、动态裁剪PHP脚本

/**
 * Author pony_chiang
 * 高性能图像裁剪方案
 * 需要php-imagick扩展
 */
ini_set ( "memory_limit", "80M" );// 请求地址比如  http://yourdomain.com/resize.php?site=www&width=300&height=200&mode=2&path=uploadfile/helloworld.png
// nginx重写规则  rewrite ^([^\.]*)/s/(.*)/(\d+)x(\d+)-(\d)/(.*) $1/s/resize.php?site=$2&width=$3&height=$4&mode=$5&path=$6 last;
$path = trim ( $_GET ['path'] );
$mode = intval ( $_GET ['mode'] );
$site = trim ( $_GET ['site'] );
$width = intval ( $_GET ['width'] );
$height = intval ( $_GET ['height'] );
$site_list = array ('www' => '/mnt/webroot/test/' );
$orig_dir = dirname ( __FILE__ );
if (! array_key_exists ( $site, $site_list )) {
    header ( 'HTTP/1.1 400 Bad Request' );
    exit ();
}
if ($mode > 3 || $mode < 0) {
    header ( 'HTTP/1.1 400 Bad Request' );
    exit ();
}
$orig_file = $site_list [$site] . $path;
if (! file_exists ( $orig_file )) {
    header ( 'HTTP/1.1 404 Not Found' );
    exit ();
}
$file_ext = '.' . pathinfo ( $path, PATHINFO_EXTENSION );
$file_name = basename ( $path, $file_ext );
$save_path = "{$orig_dir}/{$site}/{$width}x{$height}-{$mode}/{$path}";
$save_dir = dirname ( $save_path );
if (! file_exists ( $save_dir ))
    wpx_mkdir ( $save_dir );
$target_width = $width;
$target_height = $height;
$new_width = $target_width;
$new_height = $target_height;
$image = new Imagick ( $orig_file );
list ( $orig_width, $orig_height, $type, $attr ) = getimagesize ( $orig_file );
if ($mode == "0") {
    //等比缩放图像
    $new_height = $orig_height * $new_width / $orig_width;
    if ($new_height > $target_height) {
        $new_width = $orig_width * $target_height / $orig_height;
        $new_height = $target_height;
    }
} else if ($mode == "2") {
    // 放大并裁剪图像
    $desired_aspect = $target_width / $target_height;
    $orig_aspect = $orig_width / $orig_height;
    if ($desired_aspect > $orig_aspect) {
        $trim = $orig_height - ($orig_width / $desired_aspect);
        $image->cropImage ( $orig_width, $orig_height - $trim, 0, $trim / 2 );
        error_log ( "HEIGHT TRIM $trim" );
    } else {
        $trim = $orig_width - ($orig_height * $desired_aspect);
        $image->cropImage ( $orig_width - $trim, $orig_height, $trim / 2, 0 );
    }
}
$image->resizeImage ( $new_width, $new_height, imagick::FILTER_LANCZOS, 1 );
$image->writeImage ( $save_path );
header ( 'Content-Type: image/jpeg' );
header ( 'Last-Modified: ' . gmdate ( 'D, d M Y H:i:s' ) . ' GMT' );
echo file_get_contents ( $save_path );
return true;
// 循环生成目录
function wpx_mkdir($dir, $mode = 0777) {
    if (is_dir ( $dir ) || @mkdir ( $dir, $mode ))
        return true;
    if (! wpx_mkdir ( dirname ( $dir ), $mode ))
        return false;
    return @mkdir ( $dir, $mode );
}

三、nginx.conf配置

server {
        listen       80;
        server_name test.yourdomain.com;
        root   /mnt/webroot/test;
        index  index.php;
        expires 30d;        location /s {
           #只有当没有生成这张图片时才调用动态裁剪
           if (!-e $request_filename) {
             rewrite ^([^\.]*)/s/(.*)/(\d+)x(\d+)-(\d)/(.*) $1/s/resize.php?site=$2&width=$3&height=$4&mode=$5&path=$6 last;
             break;
           }
        }
        error_page   404 403 402 500 502 503 504  /404.html;
        location = /404.html {
        }
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
}

PS:在文章的末尾我要特别强调一点是关于浏览器缓存的文章,不管你是否是通过php生成的图片也好,还是使用nginx缓存生成的图片也罢,在php代码中添加一行
header('Last-Modified: ' .gmdate('D, d M Y H:i:s') . ' GMT' );

对你使用CDN有十分莫大的帮助。具体产生的效果就是客户端第一次访问此文件的http状态码是200,刷新后状态码一直都是304了。
PHP 相关文章推荐
对Session和Cookie的区分与解释
Mar 16 PHP
PHP 表单提交给自己
Jul 24 PHP
php excel类 phpExcel使用方法介绍
Aug 21 PHP
php curl请求信息和返回信息设置代码实例
Apr 27 PHP
php文件缓存方法总结
Mar 16 PHP
php基于jquery的ajax技术传递json数据简单实例
Apr 15 PHP
基于PHP生成简单的验证码
Jun 01 PHP
php_pdo 预处理语句详解
Nov 21 PHP
php简单实现单态设计模式的方法分析
Jul 28 PHP
yii2中LinkPager增加总页数和总记录数的实例
Aug 28 PHP
PHP使用redis位图bitMap 实现签到功能
Oct 08 PHP
Laravel-添加后台模板AdminLte的实现方法
Oct 08 PHP
php实现文件下载简单示例(代码实现文件下载)
Mar 10 #PHP
php实现文件编码批量转换
Mar 10 #PHP
php导出word文档与excel电子表格的简单示例代码
Mar 08 #PHP
php 创建以UNIX时间戳命名的文件夹(示例代码)
Mar 08 #PHP
PHP_Cooikes不同页面无法传递的解决方法
Mar 07 #PHP
php function用法如何递归及return和echo区别
Mar 07 #PHP
详解PHP中strlen和mb_strlen函数的区别
Mar 07 #PHP
You might like
NT IIS下用ODBC连接数据库
2006/10/09 PHP
phpmyadmin的#1251问题
2006/11/25 PHP
简单示例AJAX结合PHP代码实现登录效果代码
2008/07/25 PHP
php include,include_once,require,require_once
2008/09/05 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
Javascript的一种模块模式
2008/03/22 Javascript
ASP小贴士/ASP Tips javascript tips可以当桌面
2009/12/10 Javascript
Jquery中使用show()与hide()方法动画显示和隐藏图片
2015/10/08 Javascript
Three.js学习之几何形状
2016/08/01 Javascript
Node.js中文件操作模块File System的详细介绍
2017/01/05 Javascript
JavaScript实现左侧菜单效果
2017/12/14 Javascript
js+css实现红包雨效果
2018/07/12 Javascript
Bootstrap table表格初始化表格数据的方法
2018/07/25 Javascript
nuxt框架中对vuex进行模块化设置的实现方法
2019/09/06 Javascript
JavaScript实现简单随机点名器
2019/11/21 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
[47:53]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#2COL VS Spirit
2016/03/02 DOTA
python根据时间生成mongodb的ObjectId的方法
2015/03/13 Python
利用Python抓取行政区划码的方法
2016/11/28 Python
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
Pandas 数据框增、删、改、查、去重、抽样基本操作方法
2018/04/12 Python
python按行读取文件,去掉每行的换行符\n的实例
2018/04/19 Python
python爬取网易云音乐评论
2018/11/16 Python
python用plt画图时,cmp设置方法
2018/12/13 Python
对python 中re.sub,replace(),strip()的区别详解
2019/07/22 Python
基于Python的接口自动化unittest测试框架和ddt数据驱动详解
2021/01/27 Python
Python用requests库爬取返回为空的解决办法
2021/02/21 Python
用CSS3打造HTML5的Logo(实现代码)
2016/06/16 HTML / CSS
ASOS西班牙官网:英国在线时尚和美容零售商
2020/01/10 全球购物
银行出纳岗位职责
2013/11/25 职场文书
汽车队司机先进事迹材料
2014/02/01 职场文书
长江三峡导游词
2015/01/31 职场文书
2015年幼儿园保育工作总结
2015/05/12 职场文书
2015年度学校应急管理工作总结
2015/10/22 职场文书
python3中apply函数和lambda函数的使用详解
2022/02/28 Python
在容器中使用nginx搭建上传下载服务器
2022/05/11 Servers