设为首页 收藏本站
查看: 1121|回复: 0

[经验分享] 图片访问实时处理的实现(nodejs和php)

[复制链接]

尚未签到

发表于 2017-2-24 10:45:42 | 显示全部楼层 |阅读模式
  我在访问时光网、网易云音乐等网站时,发现将它们页面中的一些图片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 =>  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;
  
}
  至此,图片访问实时处理也就完成了。其实大部分图片服务器都需要这样的功能,而不是事先生成好几套尺寸的图片。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-346543-1-1.html 上篇帖子: Nodejs进阶:核心模块https 之 如何优雅的访问12306 下篇帖子: NodeJS中 package.json各属性分析
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表