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


Posted in NodeJs onJanuary 05, 2017

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

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

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

NodeJs 相关文章推荐
nodejs中转换URL字符串与查询字符串详解
Nov 26 NodeJs
用NodeJS实现批量查询地理位置的经纬度接口
Aug 16 NodeJs
简单好用的nodejs 爬虫框架分享
Mar 26 NodeJs
nodejs获取微信小程序带参数二维码实现代码
Apr 12 NodeJs
ajax +NodeJS 实现图片上传实例
Jun 06 NodeJs
详解nodejs中express搭建权限管理系统
Sep 15 NodeJs
使用vs code开发Nodejs程序的使用方法
Sep 21 NodeJs
nodejs实现简单的gulp打包
Dec 21 NodeJs
nodejs和react实现即时通讯简易聊天室功能
Aug 21 NodeJs
nodejs文件夹深层复制功能
Sep 03 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 NodeJs
ubuntu系统下使用pm2设置nodejs开机自启动的方法
May 12 NodeJs
nodejs实例解析(输出hello world)
Jan 03 #NodeJs
Highcharts+NodeJS搭建数据可视化平台示例
Jan 01 #NodeJs
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
Dec 30 #NodeJs
浅谈Nodejs中的作用域问题
Dec 26 #NodeJs
nodeJS删除文件方法示例
Dec 25 #NodeJs
详解nodejs 文本操作模块-fs模块(五)
Dec 23 #NodeJs
详解Nodejs的timers模块
Dec 22 #NodeJs
You might like
PHP三层结构(上) 简单三层结构
2010/07/04 PHP
PHP5下$_SERVER变量不再受magic_quotes_gpc保护的弥补方法
2012/10/31 PHP
php实现在限定区域里自动调整字体大小的类实例
2015/04/02 PHP
2017年最好用的9个php开发工具推荐(超好用)
2017/10/23 PHP
Swoole扩展的6种模式深入详解
2021/03/04 PHP
JavaScript的事件绑定(方便不支持js的时候)
2013/10/01 Javascript
JavaScript极简入门教程(三):数组
2014/10/25 Javascript
浅谈Angular4实现热加载开发旅程
2017/09/08 Javascript
微信小程序实现美团菜单
2018/06/06 Javascript
微信小程序开发背景图显示功能
2018/08/08 Javascript
vue-cli中使用高德地图的方法示例
2019/03/28 Javascript
node 解析图片二维码的内容代码实例
2019/09/11 Javascript
详解Vue+elementUI build打包部署后字体图标丢失问题
2020/07/13 Javascript
小程序自动化测试的示例代码
2020/08/11 Javascript
[01:46]新英雄登场
2019/09/10 DOTA
pytorch索引查找 index_select的例子
2019/08/18 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
解决tensorflow添加ptb库的问题
2020/02/10 Python
从多个tfrecord文件中无限读取文件的例子
2020/02/17 Python
python实现门限回归方式
2020/02/29 Python
基于pycharm 项目和项目文件命名规则的介绍
2021/01/15 Python
英国和世界各地预订便宜的酒店:LateRooms.com
2019/05/05 全球购物
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
如何掌握自荐信格式呢
2013/11/19 职场文书
《小蝌蚪找妈妈》教学反思
2014/02/21 职场文书
数学兴趣小组活动总结
2014/07/08 职场文书
幼儿园教师的自我评价范文
2014/09/17 职场文书
2015年健康教育工作总结
2015/04/10 职场文书
居委会工作总结2015
2015/05/18 职场文书
党务工作者主要事迹材料
2015/11/03 职场文书
初任公务员培训心得体会
2016/01/08 职场文书
2016社区平安家庭事迹材料
2016/02/26 职场文书
MySQL索引篇之千万级数据实战测试
2021/04/05 MySQL
利用 SQL Server 过滤索引提高查询语句的性能分析
2021/07/15 SQL Server
Python中第三方库Faker的使用详解
2022/04/02 Python