前端一直比较喜欢tinypng
压缩图片,但是每次都要用手拖来拖去,很累.
node
撸了一段100
行的代码,一个命令全自动压缩文件夹(包含子文件夹)里所有大小小于5MB
的jpg
和png
图片,亲测成功,再次感谢tinypng
。 大体思路:
- 递归获取本地文件夹里的文件
- 过滤文件,格式必须是
.jpg
.png
,大小小于5MB.(文件夹递归) - 每次只处理一个文件(可以绕过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.754299136const 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}] \n 压缩成功,原始大小-${obj.input.size},压缩大小-${ obj.output.size },优化比例-${obj.output.ratio}` ); }); }); }); req.on('error', e => { console.error(e); }); req.end();}