Maison  >  Article  >  interface Web  >  Partagez l'exemple de code qui utilise des images de nœuds pour implémenter la fonction de serveur d'images

Partagez l'exemple de code qui utilise des images de nœuds pour implémenter la fonction de serveur d'images

零下一度
零下一度original
2017-05-09 10:08:111748parcourir

Cet article présente principalement l'explication détaillée de l'utilisation de node-images pour créer un simple serveur image L'éditeur pense que c'est plutôt bien, je vais donc le partager avec vous maintenant et le donner comme référence. . Suivons l'éditeur pour y jeter un œil.

Edit : 2016-5-11 Correction de quelques erreurs évidentes dans le code et publication dans la bibliothèque ajaxjs. Le code source est ici.

Edit:2016-5-24 Ajout de la requête HEAD pour détecter la taille de l'image. S'il fait moins de 80 Ko, aucune compression n'est requise et une redirection 302 sera renvoyée.

la requête HEAD de nœud

var http = require('http'); 
var url = require('url'); 
var siteUrl = url.parse('http://img1.gtimg.com/view/pics/hv1/42/80/2065/134297067.jpg'); 
 
request = http.request({ 
  method : 'HEAD', 
  port: siteUrl.port || 80, 
  host: siteUrl.host, 
  path : siteUrl.pathname 
}); 
request.on('response', function (response) { 
  response.setEncoding('utf8'); 
  console.log(response.headers['content-length']); 
}); 
request.end();

doit d'abord aimer le travail de la bibliothèque chinoise npm : node-images (github.com/zhangyuanwei/node-images), qui encapsule le multiplateforme La logique C++ forme l'API nodejs que nous, les novices, pouvons utiliser avec plaisir. J'ai déjà utilisé GraphicsMagick pour nodejs, qui est le plus puissant, mais la taille du package est relativement grande et fortement dépendante. Il semble que des vulnérabilités aient été signalées récemment. Par rapport à GM, node-images est principalement plus léger et ne nécessite l'installation d'aucune bibliothèque de traitement d'image.

Installez node-images :

npm install images

Le package npm est relativement volumineux. Il existe un package compressé node-images.tar.gz dans node_modules. téléchargement, mais il reste également 11 Mo.

Serveur d'images, les exigences actuelles sont : un serveur statique qui prend en charge le retour de jpg/png/gif ; prend en charge la mise en cache HTTP ; prend en charge le chargement d'images à distance ; Pour charger des images distantes, vous pouvez limiter la taille du fichier image en définissant maxLength.

Pendant le processus de mise en œuvre, Step.js a été utilisé pour participer à des opérations asynchrones, ce qui était relativement simple.

Configuration liée au serveur :

// 配置对象。 
var staticFileServer_CONFIG = { 
  'host': '127.0.0.1',      // 服务器地址 
  'port': 3000,        // 端口 
  'site_base': 'C:/project/bigfoot',   // 根目录,虚拟目录的根目录 
  'file_expiry_time': 480,    // 缓存期限 HTTP cache expiry time, minutes 
  'directory_listing': true    // 是否打开 文件 列表 
};

Exemple de requête :

localhost:3001/asset/coming_soon.jpg?w=300
localhost:3001/asset/coming_soon.jpg?h=150
localhost:3001/asset/coming_soon.jpg?w=300&h=150
localhost:3001/?url=http://s0.hao123img com. /res/img/logo/logonew.png

Code source complet :

const 
  HTTP = require('http'), PATH = require('path'), fs = require('fs'), CRYPTO = require('crypto'), 
  url = require("url"), querystring = require("querystring"), 
  Step = require('./step'), images = require("images"); 
 
// 配置对象。 
var staticFileServer_CONFIG = { 
  'host': '127.0.0.1',      // 服务器地址 
  'port': 3001,            // 端口 
  'site_base': 'C:/project/bigfoot',     // 根目录,虚拟目录的根目录 
  'file_expiry_time': 480,    // 缓存期限 HTTP cache expiry time, minutes 
  'directory_listing': true    // 是否打开 文件 列表 
}; 
 
const server = HTTP.createServer((req, res) => { 
  init(req, res, staticFileServer_CONFIG); 
}); 
 
server.listen(staticFileServer_CONFIG.port, staticFileServer_CONFIG.host, () => { 
  console.log(`Image Server running at http://${staticFileServer_CONFIG.host}:${staticFileServer_CONFIG.port}/`); 
}); 
 
// 当前支持的 文件类型,你可以不断扩充。 
var MIME_TYPES = { 
  '.txt': 'text/plain', 
  '.md': 'text/plain', 
  '': 'text/plain', 
  '.html': 'text/html', 
  '.css': 'text/css', 
  '.js': 'application/javascript', 
  '.json': 'application/json', 
  '.jpg': 'image/jpeg', 
  '.png': 'image/png', 
  '.gif': 'image/gif' 
}; 
 
MIME_TYPES['.htm'] = MIME_TYPES['.html']; 
 
var httpEntity = { 
  contentType: null, 
  data: null, 
  getHeaders: function (EXPIRY_TIME) { 
    // 返回 HTTP Meta 的 Etag。可以了解 md5 加密方法 
    var hash = CRYPTO.createHash('md5'); 
    //hash.update(this.data); 
    //var etag = hash.digest('hex'); 
 
    return { 
      'Content-Type': this.contentType, 
      'Content-Length': this.data.length, 
      //'Cache-Control': 'max-age=' + EXPIRY_TIME, 
      //'ETag': etag 
    }; 
  } 
}; 
 
function init(request, response) { 
  var args = url.parse(request.url).query,     //arg => name=a&id=5  
    params = querystring.parse(args); 
 
  if (params.url) { 
    getRemoteImg(request, response, params); 
  } else { 
    load_local_img(request, response, params); 
  } 
} 
 
// 加载远程图片 
function getRemoteImg(request, response, params) { 
  var imgData = ""; // 字符串 
  var size = 0; 
  var chunks = []; 
 
  Step(function () { 
      HTTP.get(params.url, this); 
    }, 
    function (res) { 
      var maxLength = 10; // 10mb 
      var imgData = ""; 
      if (res.headers['content-length'] > maxLength * 1024 * 1024) { 
        server500(response, new Error('Image too large.')); 
      } else if (!~[200, 304].indexOf(res.statusCode)) { 
        server500(response, new Error('Received an invalid status code.')); 
      } else if (!res.headers['content-type'].match(/image/)) { 
        server500(response, new Error('Not an image.')); 
      } else { 
        // res.setEncoding("binary"); //一定要设置response的编码为binary否则会下载下来的图片打不开 
        res.on("data", function (chunk) { 
          // imgData+=chunk; 
          size += chunk.length; 
          chunks.push(chunk); 
        }); 
 
        res.on("end", this); 
      } 
       
    }, 
    function () {  
      imgData = Buffer.concat(chunks, size); 
     
      var _httpEntity = Object.create(httpEntity); 
      _httpEntity.contentType = MIME_TYPES['.png']; 
      _httpEntity.data = imgData; 
      // console.log('imgData.length:::' + imgData.length) 
      // 缓存过期时限 
      var EXPIRY_TIME = (staticFileServer_CONFIG.file_expiry_time * 60).toString(); 
      response.writeHead(200); 
      response.end(_httpEntity.data); 
    } 
  ); 
   
} 
 
// 获取本地图片 
function load_local_img(request, response, params) { 
  if (PATH.extname(request.url) === '') { 
    // connect.directory('C:/project/bigfoot')(request, response, function(){}); 
    // 如果 url 只是 目录 的,则列出目录 
    console.log('如果 url 只是 目录 的,则列出目录'); 
    server500(response, '如果 url 只是 目录 的,则列出目录@todo'); 
  } else { 
    var pathname = require('url').parse(request.url).pathname; 
    // 如果 url 是 目录 + 文件名 的,则返回那个文件 
    var path = staticFileServer_CONFIG.site_base + pathname; 
 
    Step(function () { 
      console.log('请求 url :' + request.url + ', path : ' + pathname); 
      fs.exists(path, this); 
    }, function (path_exists, err) { 
      if (err) { 
        server500(response, '查找文件失败!'); 
        return; 
      } 
      if (path_exists) { 
        fs.readFile(path, this); 
      } else { 
        response.writeHead(404, { 'Content-Type': 'text/plain;charset=utf-8' }); 
        response.end('找不到 ' + path + '\n'); 
      } 
    }, function (err, data) { 
      if (err) { 
        server500(response, '读取文件失败!'); 
        return; 
      } 
      var extName = '.' + path.split('.').pop(); 
      var extName = MIME_TYPES[extName] || 'text/plain'; 
 
      var _httpEntity = Object.create(httpEntity); 
      _httpEntity.contentType = extName; 
      var buData = new Buffer(data); 
      //images(buData).height(100); 
 
      var newImage; 
 
      if (params.w && params.h) { 
        newImage = images(buData).resize(Number(params.w), Number(params.h)).encode("jpg", { operation: 50 }); 
      } else if (params.w) { 
        newImage = images(buData).resize(Number(params.w)).encode("jpg", { operation: 50 }); 
      } else if (params.h) { 
        newImage = images(buData).resize(null, Number(params.h)).encode("jpg", { operation: 50 }); 
      } else { 
        newImage = buData; // 原图 
      } 
 
      _httpEntity.data = newImage; 
 
      // 命中缓存,Not Modified返回 304 
      if (request.headers.hasOwnProperty('if-none-match') && request.headers['if-none-match'] === _httpEntity.ETag) { 
        response.writeHead(304); 
        response.end(); 
      } else { 
        // 缓存过期时限 
        var EXPIRY_TIME = (staticFileServer_CONFIG.file_expiry_time * 60).toString(); 
 
        response.writeHead(200, _httpEntity.getHeaders(EXPIRY_TIME)); 
        response.end(_httpEntity.data); 
      } 
    }); 
  } 
} 
function server500(response, msg) { 
  console.log(msg); 
  response.writeHead(404, { 'Content-Type': 'text/plain;charset=utf-8' }); 
  response.end(msg + '\n'); 
} 
加水印也是可以的。例子如下。
var images = require('images'); 
var path = require('path'); 
var watermarkImg = images(path.join(dirname, 'path/to/watermark.ext')); 
var sourceImg = images(path.join(dirname, 'path/to/sourceImg.ext')); 
var savePath = path.join(dirname, 'path/to/saveImg.jpg'); 
 
// 比如放置在右下角,先获取原图的尺寸和水印图片尺寸 
var sWidth = sourceImg.width(); 
var sHeight = sourceImg.height(); 
var wmWidth = watermarkImg.width(); 
var wmWidth = watermarkImg.height(); 
 
images(sourceImg) 
 // 设置绘制的坐标位置,右下角距离 10px 
 .draw(watermarkImg, sWidth - wmWidth - 10, sHeight - wmHeight - 10) 
 // 保存格式会自动识别 
 .save(savePath);

[Recommandations associées]

1. Tutoriel vidéo

2.

Manuel de référence JavaScript chinois

3

php.cn Dugu Jiujian (3) - Tutoriel vidéo JavaScript <.>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn