欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-02 22:02:04
我在访问时光网、网易云音乐等网站时,发现将它们页面中的一些图片url修改一下就可以得到不同尺寸的图片,于是思考了其实现方案,我的思路是:url rewrite + 实时处理...

我在访问时光网、网易云音乐等网站时,发现将它们页面中的一些图片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 rewrite_module modules/mod_rewrite.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;
}

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。