Nodejs全自動使用Tinypng(無料版、構成不要)圧縮画像

3544 ワード

フロントエンドはずっとtinypngの圧縮画像が好きですが、毎回手で引きずって、疲れています.最近忙しくなくて、nodeは1段の100行のコードを引っ張って、1つの命令の全自動圧縮フォルダ(サブフォルダを含む)の中ですべての大きさが5MBより小さいjpgpngのピクチャー、親測は成功して、再びtinypngに感謝します.
基本的な考え方:
  • ローカルフォルダ内のファイルを再帰的に取得する
  • フィルタファイル、フォーマットは.jpg .pngでなければならず、サイズは5 MB未満である.(フォルダ再帰)
  • 毎回1つのファイルのみを処理(20個の数量制限を迂回可能)
  • は、戻るデータを処理して、リモート最適化ピクチャアドレス
  • を取得する.
  • 画像を取り戻すローカル画像
  • を更新する.
  • 純node実装他のコードフラグメントに依存しない
  • 上のコード:
    const fs = require('fs');
    const path = require('path');
    const https = require('https');
    const crypto = require('crypto');
    const { URL } = require('url');
    
    const root = './',
      exts = ['.jpg', '.png'],
      max = 5200000; // 5MB == 5242848.754299136
    
    const options = {
      method: 'POST',
      hostname: 'tinypng.com',
      path: '/web/shrink',
      headers: {
        rejectUnauthorized: false,
        'Postman-Token': Date.now(),
        'Cache-Control': 'no-cache',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent':
          'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
      }
    };
    
    fileList(root);
    
    //       
    function fileList(folder) {
      fs.readdir(folder, (err, files) => {
        if (err) console.error(err);
        files.forEach(file => {
          fileFilter(folder + file);
        });
      });
    }
    
    //       ,    jpg,png  
    function fileFilter(file) {
      fs.stat(file, (err, stats) => {
        if (err) return console.error(err);
        if (
          //      ,  5MB,   jpg||png
          stats.size <= max &&
          stats.isFile() &&
          exts.includes(path.extname(file))
        ) {
          fileUpload(file); // console.log('    :' + file);
        }
        if (stats.isDirectory()) fileList(file + '/');
      });
    }
    //   API,    
    // {"error":"Bad request","message":"Request is invalid"}
    // {"input": { "size": 887, "type": "image/png" },"output": { "size": 785, "type": "image/png", "width": 81, "height": 81, "ratio": 0.885, "url": "https://tinypng.com/web/output/7aztz90nq5p9545zch8gjzqg5ubdatd6" }}
    function fileUpload(img) {
      var req = https.request(options, function(res) {
        res.on('data', buf => {
          let obj = JSON.parse(buf.toString());
          if (obj.error) {
            console.log(`[${img}]:    !  :${obj.message}`);
          } else {
            fileUpdate(img, obj);
          }
        });
      });
    
      req.write(fs.readFileSync(img), 'binary');
      req.on('error', e => {
        console.error(e);
      });
      req.end();
    }
    //         ,      
    function fileUpdate(imgpath, obj) {
      let options = new URL(obj.output.url);
      let req = https.request(options, res => {
        let body = '';
        res.setEncoding('binary');
        res.on('data', function(data) {
          body += data;
        });
    
        res.on('end', function() {
          fs.writeFile(imgpath, body, 'binary', err => {
            if (err) return console.error(err);
            console.log(
              `[${imgpath}] 
    , -${obj.input.size}, -${ obj.output.size }, -${obj.output.ratio}` ); }); }); }); req.on('error', e => { console.error(e); }); req.end(); }