分享

基于Nginx + Perl/PHP + ImageMagick按需实时生成且缓存缩略图 | PHP |

 WindySky 2016-07-04

摘要: nginx内嵌Perl脚本实现缩略图生成 安装所需软件 安装ImageMagick及Perl Imager: # yum install ImageMagick ImageMagick-perl...

nginx内嵌Perl脚本实现缩略图生成

  • 安装所需软件

    安装ImageMagick及Perl Imager:

    # yum install ImageMagick ImageMagick-perl perl-YAML
    # yum install giflib-devel libjpeg-devel libtiff-devel libpng-devel freetype-devel
    # cpan -i Imager
    

    查看当前支持的图片格式:

    # perl -MImager -e 'print join "\n", sort keys %Imager::formats'
    

    安装nginx(启用HttpPerlModule):

    # ./configure --with-http_perl_module --with-pcre
    # make && make install
    
  • nginx配置

    nginx配置例子:

    [root@centos191 lib]# cat /usr/local/nginx/conf/nginx.conf
    
    ...
        perl_modules perl/lib;
        perl_require resizer.pm;
        server {
            listen       80;
            server_name  images.;
            root   /data/www/qingluobo;
            index index.html;
    
            #error_page  404              /404.html;
    
    	location /img {
    	    try_files $uri @rewrite;
    	}
    	location @rewrite {
    	    rewrite ^(.*)(.jpg|.JPG|.gif|.GIF|.png|.PNG)$ /scale$1$2 last;
    	}
    	location /scale {
    	    internal;
         	    perl resize::handler;
        	}	
        }
    ...
    
  • Perl脚本

    Perl脚本例子:

    # mkdir -p /usr/local/nginx/perl/lib
    # cd /usr/local/nginx/perl/lib
    # cat resizer.pm
    
    package resize;
    use nginx;
    use Image::Magick;
    our $base_dir="/data/www/qingluobo";
    our $image;
     
    sub handler {
      my $r = shift;
      return DECLINED unless $r->uri =~ m/\.thumb\.\d{1,}?x\d{1,}?\./;
      my $uri=$r->uri;
      $uri=~ s!^/scale!!;
     
      my $dest_file="$base_dir/$uri";
      my @path_tokens=split("/", $uri);
      my $filename=pop @path_tokens;
      my @filename_tokens=split('\.', $filename);
     
      # We know  the last part is the extension;
      # We know the one before that is the dimensions
      # We know that the one before that is the resize_to string
     
      my $ext=pop @filename_tokens;
      my $dimensions=pop @filename_tokens;
      pop @filename_tokens;
      $filename=join('.', @filename_tokens, $ext);
     
      my $real_file_path=join("/",   $base_dir, @path_tokens, $filename);
      return DECLINED unless -f $real_file_path;
     
      my ($width,$height)=split("x", $dimensions);
      if ($height<1) {
        $dimensions=$width;
      }
     
      $image= new Image::Magick;
      $image->Read($real_file_path);
      $image->Scale($dimensions);
      $image->Write($dest_file);
      $r->sendfile($dest_file);
      return OK;
     
    }
     
    1;
    __END__
    
  • 访问测试

    原图:http://images./img/test.jpg
    缩略图1:http://images./img/test.thumb.400×400.jpg
    缩略图2:http://images./img/test.thumb.600×0.jpg

php脚本实现缩略图生成

  • nginx配置

    nginx配置例子:

    server {
            listen       80;
            server_name  images.;
            root   /data/www/qingluobo;
            index index.html index.php;
    
            #error_page  404              /404.html;
    
            location ~ ^/thumbs/(.*) {
               try_files $uri @resize;
               expires 4h;
            }        
            location @resize {
               internal;
               rewrite ^(?:.*)(?:.jpg|.JPG|.gif|.GIF|.png|.PNG)$ /resize.php?ReqURI=$uri last;
    	}
    	location = /resize.php {
               internal;
               fastcgi_pass   127.0.0.1:9000;
               #fastcgi_index  index.php;
               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
               include        fastcgi_params;
    	}
    ...
    }
    
  • php脚本

    需要安装php扩展imagick.
    php脚本例子:

    <?php
    if ( empty($_GET['ReqURI']) ) {
    	exit('Invalid Param for ReqURI');
    }
    
    $uri = $_GET['ReqURI'];
    
    // whether to allow creating new directory
    $locked_dir_creation = false;
    
    $source_path = dirname(str_replace('/thumbs', '',$uri));
    
    $base_dir = "/data/www/qingluobo";
    $path_tokens = explode('/', $uri);
    $filename = array_pop($path_tokens);
    
    if ( !preg_match('/(.*)_(\d+)x(\d+)_([1-3])\.(jpe?g|png|gif)/i', $filename, $matches) ){
        header("Status: 404 Not Found");
        echo 'invalid filename :' . $filename;
        exit;
    }
    
    $source_file = $base_dir . $source_path . '/' . $matches[1];
    if ( !is_file($source_file) ) {
        header("Status: 404 Not Found");
        echo $filename . ' Not Found';
        exit;
    }
    
    $dest_path = $base_dir . implode('/', $path_tokens);
    if ( !is_dir($dest_path) && $locked_dir_creation ) {
        header('Status: 403 Forbidden');
        echo 'Directory creation is forbidden.';
        exit;
    }
    
    $new_width = $target_width = $matches[2];
    $new_height = $target_height = $matches[3];
    $mode = $matches[4];
    $target_format = strtolower($matches[5]);
    
    $source_img = new Imagick($source_file);
    $dimension = $source_img->getImageGeometry();
    $orig_width = $dimension['width'];
    $orig_height = $dimension['height'];
    switch ($mode) {
        case '1': 
        break;
        case '2':   
            /*preserve aspect ratio, resize the image to specified box,
              resized image will be of specified dimension or smaller */
            $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;
    	}
        break;
    	case '3': 
                /*zoom and crop the image to fill the specified dimension*/
                // crop to get desired aspect ration
    	    $desired_aspect = $target_width / $target_height;
    	    $orig_aspect = $orig_width / $orig_height;
    		
    	    if ($desired_aspect > $orig_aspect) {
    	        $trim = $orig_height - ($orig_width / $desired_aspect);
    		$source_img->cropImage($orig_width, $orig_height-$tirm, 0, $trim /2);
    	    } else {
    		$trim = $orig_width - ($orig_height * $desired_aspect);
    		$source_img->cropImage($orig_width-$trim, $orig_height, $trim/2, 0);
    	    }
        break;
    }
    
    /* default mode 1, stretch image to fit the specified dimensions without preserving aspect ratio */
    $source_img->resizeImage($new_width, $new_height, imagick::FILTER_LANCZOS, 1); 
    
    if ( !is_dir($dest_path) && !mkdir($dest_path, 0755, true) ) {
    	echo 'cannot create dir : ' . $dest_path;
    	exit;
    }
    
    $dest_file = $dest_path . '/' . $matches[0];
    
    //file_put_contents($dest_file, $source_img);
    clearstatcache($dest_path);
    $source_img->writeImage($dest_file);
    
    header("Content-Type: image/$target_format");
    echo $source_img;
    
  • 访问测试

    原图:http://images./img/test.jpg
    缩略图(mode 1):http://images./thumbs/img/test.jpg_300x300_1.jpg
    缩略图(mode 2):http://images./thumbs/img/test.jpg_300x300_2.jpg
    缩略图(mode 3):http://images./thumbs/img/test.jpg_300x300_3.jpg

图片缓存

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多