nodejs和php實(shí)現(xiàn)圖片訪問(wèn)實(shí)時(shí)處理
我在訪問(wèn)時(shí)光網(wǎng)、網(wǎng)易云音樂等網(wǎng)站時(shí),發(fā)現(xiàn)將它們頁(yè)面中的一些圖片URL修改一下就可以得到不同尺寸的圖片,于是思考了其實(shí)現(xiàn)方案,我的思路是:URL Rewrite + 實(shí)時(shí)處理 + 緩存,對(duì)用戶請(qǐng)求的URL進(jìn)行重寫,然后利用圖片處理類庫(kù)對(duì)圖片進(jìn)行處理,接著緩存該尺寸圖片并輸出到瀏覽器。使用PHP和Node.js實(shí)現(xiàn)了一遍,基本達(dá)到了需要的效果。
1、Nginx+Node.js(express)實(shí)現(xiàn)
URL重寫
這里Nginx主要是做一個(gè)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; }
這里說(shuō)明一下:Nginx監(jiān)聽本地的80端口,Node.js監(jiān)聽的是3000端口。當(dāng)用戶訪問(wèn)類似http://127.0.0.1/upload/147332819224704_400x300.jpg的地址時(shí),便會(huì)被代理到http://127.0.0.1:3000/resize?src=147332819224704&w=400&h=300&type=jpg訪問(wèn),看起來(lái)像是訪問(wèn)一張圖片,其實(shí)不然。
圖片實(shí)時(shí)處理
我們?cè)贜ode.js中實(shí)時(shí)處理圖片,進(jìn)行縮放、模糊、水印等操作,之后將其緩存起來(lái)并輸出到瀏覽器。Node.js自身API并不擅長(zhǎng)圖片的處理,我們可以借助第三方類庫(kù)來(lái)實(shí)現(xiàn),這里推薦GraphicsMagick或ImageMagick,使用它們之前先安裝gm模塊:
npm install gm --save
接著便可以使用GraphicsMagick了,該模塊的API可以參考GM模塊API介紹。圖片處理的實(shí)現(xiàn)如下:
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; }
如上代碼所示,當(dāng)用戶訪問(wèn)http://127.0.0.1/upload/147332819224704_400x300.jpg時(shí),如果147332819224704這張圖片存在,且400x300這個(gè)尺寸也存在,則直接輸出這張圖片,如不存在,則生成一張?jiān)摮叽绲膱D片保存并輸出到瀏覽器。如果提供的尺寸超出了圖片的原始尺寸,則直接輸出原圖。我們不僅可以修改尺寸,也可以進(jìn)行模糊、打水印等操作,這里就不多介紹了。
如果不用Nginx反向代理也是可以的,使用express的正則路由實(shí)現(xiàn),如下所示:
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實(shí)現(xiàn)
首先得搭建windows下php開發(fā)環(huán)境,我本人用的是apache2+php5.6,具體的搭建步驟網(wǎng)上一大堆,便不再累述。
開啟apache rewrite功能
首先我們得開啟Apache rewrite模塊功能,去掉配置文件http.conf中LoadModule rewrite_module modules/mod_rewrite.so前面的注釋,然后設(shè)置Directory塊下AllowOverride All,可能有多處,接著重啟Apache服務(wù)。
配置.htaccess文件
在DocumentRoot目錄下,新建.htaccess文件,如果創(chuàng)建不了,可以先創(chuàng)建一個(gè)文本,然后另存為,在彈出的對(duì)話框文件名處填寫".htaccess"即可。之后,編寫URL重寫規(guī)則,如下所示:
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。
功能實(shí)現(xiàn)
接下來(lái)便是功能的實(shí)現(xiàn),邏輯和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; }
至此,圖片訪問(wèn)實(shí)時(shí)處理也就完成了。其實(shí)大部分圖片服務(wù)器都需要這樣的功能,而不是事先生成好幾套尺寸的圖片。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- nginx配置訪問(wèn)圖片路徑以及html靜態(tài)頁(yè)面的調(diào)取方法
- php如何控制用戶對(duì)圖片的訪問(wèn) PHP禁止圖片盜鏈
- SpringMVC上傳圖片與訪問(wèn)
- Android互聯(lián)網(wǎng)訪問(wèn)圖片并在客戶端顯示的方法
- PHP在Windows IIS上傳的圖片無(wú)法訪問(wèn)的解決方法
- 使用AngularJS 應(yīng)用訪問(wèn) Android 手機(jī)的圖片庫(kù)
- 解決jsp頁(yè)面使用網(wǎng)絡(luò)路徑訪問(wèn)圖片的亂碼問(wèn)題
- js 利用image對(duì)象實(shí)現(xiàn)圖片的預(yù)加載提高訪問(wèn)速度
- Asp.Net二級(jí)域名共享Forms身份驗(yàn)證、下載站/圖片站的授權(quán)訪問(wèn)控制
- 輕松創(chuàng)建nodejs服務(wù)器(10):處理上傳圖片
相關(guān)文章
使用nodejs搭建微信小程序支付接口的詳細(xì)過(guò)程
前段時(shí)間做微信支付,遇到了很多坑,網(wǎng)上也沒有講解的特別明白的,通過(guò)借鑒各路人才的經(jīng)驗(yàn),最后也完成了,下面這篇文章主要給大家介紹了關(guān)于使用nodejs搭建微信小程序支付接口的詳細(xì)過(guò)程,需要的朋友可以參考下2022-12-12node.js+captchapng+jsonwebtoken實(shí)現(xiàn)登錄驗(yàn)證示例
本篇文章主要介紹了node.js+captchapng+jsonwebtoken實(shí)現(xiàn)登錄驗(yàn)證示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08我用的一些Node.js開發(fā)工具、開發(fā)包、框架等總結(jié)
這篇文章主要介紹了我個(gè)人使用的一些Node.js開發(fā)工具、開發(fā)包、框架等總結(jié),需要的朋友可以參考下2014-09-09深入學(xué)習(xí)nodejs中的async模塊的使用方法
本篇文章主要介紹了nodejs中的async模塊的使用方法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Nodejs使用archiver-zip-encrypted庫(kù)加密壓縮文件時(shí)報(bào)錯(cuò)(解決方案)
這篇文章主要介紹了Nodejs使用archiver-zip-encrypted庫(kù)加密壓縮文件時(shí)報(bào)錯(cuò),朋友朋友在測(cè)試過(guò)程中都出現(xiàn)過(guò)異常,下面小編把問(wèn)題過(guò)程分析腳本之家平臺(tái),需要的朋友可以參考下2019-11-11Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用詳解
node-schedule是 Node.js 的一個(gè)定時(shí)任務(wù)(crontab)模塊。這篇文章主要介紹了Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用,需要的朋友可以參考下2020-04-04