nodejs和php实现图片访问实时处理

我在访问时光网、实现实网易云音乐等网站时,图片发现将它们页面中的访问一些图片URL修改一下就可以得到不同尺寸的图片,于是处理思考了其实现方案,我的实现实思路是:URL Rewrite + 实时处理 + 缓存,对用户请求的图片URL进行重写,然后利用图片处理类库对图片进行处理,访问接着缓存该尺寸图片并输出到浏览器。处理使用PHP和Node.js实现了一遍,实现实基本达到了需要的图片效果。

1、访问Nginx+Node.js(express)实现 

URL重写 这里Nginx主要是处理做一个URL重写和反向代理的功能,配置如下所示:

location ~ /upload/{    if ($request_uri ~* ^/upload/(.+)_(\d+)x(\d+)\.(jpg|png|gif)$) {      set $src $1;     set $w $2;     set $h $3;     set $t $4;     rewrite . /resize?实现实src=$src&w=$w&h=$h&type=$t break;   }   proxy_pass    http://127.0.0.1:3000; }  

这里说明一下:Nginx监听本地的80端口,Node.js监听的图片是3000端口。当用户访问类似http://127.0.0.1/upload/147332819224704_400x300.jpg的访问地址时,便会被代理到http://127.0.0.1:3000/resize?src=147332819224704&w=400&h=300&type=jpg访问,看起来像是访问一张图片,其实不然。 图片实时处理 我们在Node.js中实时处理图片,进行缩放、源码库模糊、水印等操作,之后将其缓存起来并输出到浏览器。Node.js自身API并不擅长图片的处理,我们可以借助第三方类库来实现,这里推荐GraphicsMagick或ImageMagick,使用它们之前先安装gm模块: npm install gm --save 接着便可以使用GraphicsMagick了,该模块的API可以参考GM模块API介绍。图片处理的实现如下:

app.get(/resize,function(req,res){    var src = req.query.src,     width = req.query.w,     height = req.query.h,     type = req.query.type;   var imgFile = uploadDir+src+.+type;   var notFound = 不好意思,该图片不存在或已被删除!;   var thumb = getThumbImg(src,width,height,type);   if(isFileExists(imgFile)){      if(isFileExists(thumb)){        res.type(type).sendFile(__dirname+/+thumb);     }else{        imgResize(imgFile,thumb,width,height,type,res);     }   }else{      res.status(404).send(notFound);   } }); function imgResize(f,th,w,h,t,r){    var imgSize = sizeOf(f);   if(!w||!h||w>=imgSize.width||h>=imgSize.height){      r.type(t).sendFile(__dirname+/+f);   }else{      imageMagick(f)       .resize(w,h,!)        .stream(function(err, stdout, stderr) {          if (err) {            console.log(err);           res.end();         }         var ws = fs.createWriteStream(th);         stdout.pipe(ws);         r.type(t);         stdout.pipe(r);       });   } } function isFileExists(filePath){    var bool = !0;   try{      fs.accessSync(filePath,fs.constants.F_OK);   }catch(err){      bool = !1;   }   return bool; }  

如上代码所示,当用户访问http://127.0.0.1/upload/147332819224704_400x300.jpg时,如果147332819224704这张图片存在,且400x300这个尺寸也存在,则直接输出这张图片,如不存在,则生成一张该尺寸的图片保存并输出到浏览器。如果提供的尺寸超出了图片的原始尺寸,则直接输出原图。我们不仅可以修改尺寸,也可以进行模糊、打水印等操作,这里就不多介绍了。 如果不用Nginx反向代理也是可以的,使用express的正则路由实现,网站模板如下所示:

app.get(/^\/upload\/(.+)_(\d+)x(\d+)\.(jpg|png|gif)$/,function(req,res){    var src = RegExp.$1,     width = RegExp.$2,     height = RegExp.$3,     type = RegExp.$4;   var imgFile = uploadDir+src+.+type;   var notFound = 不好意思,该图片不存在或已被删除!;   var thumb = getThumbImg(src,width,height,type);   if(isFileExists(imgFile)){      if(isFileExists(thumb)){        res.type(type).sendFile(__dirname+/+thumb);     }else{        imgResize(imgFile,thumb,width,height,type,res);     }   }else{      res.status(404).send(notFound);   } });  

2、Apache+PHP实现 首先得搭建windows下php开发环境,我本人用的是apache2+php5.6,具体的搭建步骤网上一大堆,便不再累述。 开启apache rewrite功能 首先我们得开启Apache rewrite模块功能,去掉配置文件http.conf中LoadModule rewritemodule modules/modrewrite.so前面的注释,然后设置Directory块下AllowOverride All,可能有多处,接着重启Apache服务。 配置.htaccess文件 在DocumentRoot目录下,新建.htaccess文件,如果创建不了,可以先创建一个文本,然后另存为,在弹出的对话框文件名处填写".htaccess"即可。之后,编写URL重写规则,如下所示:

RewriteEngine on RewriteCond %{ REQUEST_FILENAME} !-f RewriteRule ^upload/(.+)_([0-9]+)x([0-9]+)\.(jpg|png|gif)$ resize.php?src=$1&w=$2&h=$3&type=$4 [L]  

将类似http://127.0.0.1/upload/147332819224704_400x300.jpg地址重写为http://127.0.0.1/resize.php/src=147332819224704&w=400&h=300&type=jpg。 功能实现 接下来便是功能的实现,逻辑和nodejs版逻辑一致,代码如下:

function getThumbImg($src,$w,$h,$type) {    global $thumbs;   return $_SERVER[DOCUMENT_ROOT].$thumbs.$src._.$w._.$h...$type; } function imgResize($f,$th,$w,$h,$t) {    $imagick = new Imagick();   $imagick->readImage($_SERVER[DOCUMENT_ROOT].\\.$f);   $width = $imagick->getImageWidth();   $height = $imagick->getImageHeight();   if(!$w||!$h||$w>=$width||$h>=$height){      header(Content-Type:image/.$t);     echo file_get_contents($_SERVER[DOCUMENT_ROOT].\\.$f);   }else{      $imagick->stripImage();     $imagick->cropThumbnailImage($w, $h);     $imagick->writeImage($th);     header(Content-Type:image/.$t);     echo $imagick->getImageBlob();     $imagick->clear();     $imagick->destroy();   } } $uploadDir = "uploads/images/"; $thumbs = "uploads/thumbs/"; $src = $_GET[src]; $width = $_GET[w]; $height = $_GET[h]; $type = $_GET[type]; $imgFile = $uploadDir.$src...$type; $notFound = 不好意思,该图片不存在或已被删除!; $thumb = getThumbImg($src,$width,$height,$type); if(file_exists($imgFile)){    if(file_exists($thumb)){      header(Content-Type:image/.$type);     echo file_get_contents($thumb);   }else{      imgResize($imgFile,$thumb,$width,$height,$type);   } }else{    header("HTTP/1.0 404 Not Found");   header("status: 404");   echo $notFound; }  

至此,图片访问实时处理也就完成了。其实大部分图片服务器都需要这样的亿华云计算功能,而不是事先生成好几套尺寸的图片。 

系统运维
上一篇:Web 服务器静态资源加速技术
下一篇:5 种最有发展前景的 AI 硬件技术