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

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

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

nodejs和php实现图片访问实时处理的更多相关文章

  1. 从iOS应用程序发送帖子到PHP脚本不工作…简单的解决方案就像

    我之前已经做了好几次了但是由于某些原因我无法通过这个帖子…我尝试了设置为_POST且没有的变量的PHP脚本……当它们未设置为发布时它工作精细.这是我的iOS代码:这里是PHP的一大块,POST变量不在正确的位置?我想这对于更有经验的开发人员来说是一个相当简单的答案,感谢您的帮助!解决方法$_POST是一个数组,而不是一个函数.您需要使用方括号来访问数组索引:

  2. swift学习2 元组 tuples

    swift中出现了一种新的数据结构,非常牛掰的元组tuples如果懂PHP的猿,会发现这个元组和PHP的数组非常类似,同样是可以默认不指定key,也可以指定key目前的学习疑问是,如何进行元组的遍历?

  3. 尝试使用swift mailer,gmail smtp,php发送邮件

    这里是我的代码:在运行时出现此错误…

  4. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  5. jQuery的Cookie封装,与PHP交互的简单实现

    下面小编就为大家带来一篇jQuery的Cookie封装,与PHP交互的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  7. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  8. 如何在PHP环境中使用ProtoBuf数据格式

    这篇文章主要介绍了如何在PHP环境中使用ProtoBuf数据格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  9. PHP rsa加密解密算法原理解析

    这篇文章主要介绍了PHP rsa加密解密算法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  10. PHP cookie与session会话基本用法实例分析

    这篇文章主要介绍了PHP cookie与session会话基本用法,结合实例形式分析了PHP cookie与session会话基本存储、设置、删除等相关使用方式,需要的朋友可以参考下

随机推荐

  1. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  2. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  3. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  4. nodejs模块学习之connect解析

    这篇文章主要介绍了nodejs模块学习之connect解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  6. 详解koa2学习中使用 async 、await、promise解决异步的问题

    这篇文章主要介绍了详解koa2学习中使用 async 、await、promise解决异步的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. Node.js编写爬虫的基本思路及抓取百度图片的实例分享

    这篇文章主要介绍了Node.js编写爬虫的基本思路及抓取百度图片的实例分享,其中作者提到了需要特别注意GBK转码的转码问题,需要的朋友可以参考下

  8. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  10. node下使用UglifyJS压缩合并JS文件的方法

    下面小编就为大家分享一篇node下使用UglifyJS压缩合并JS文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

返回
顶部