# node、imagemin实现缩略图的过程

6 篇文章 1 订阅

安装库

import imagemin from "imagemin";
import bluebird from "bluebird";
import imageminMozjpeg from "imagemin-mozjpeg";
import imageminPngquant from "imagemin-pngquant";

//版本
"imagemin": "^7.0.1",
"imagemin-mozjpeg": "^8.0.0",
"imagemin-pngquant": "^6.0.1",
"bluebird": "^3.7.2"

普通方法

(async () => {
	await imagemin(['images/*.png'], {
		destination: 'build/images',
		plugins: [
			imageminPngquant({ quality: 50 })
		]
	});

	console.log('Images optimized');
})();

异步方法

Promise.promisify(fs.readFile)(sourcepath)
        .then((buffer) => {
          return imagemin.buffer(buffer, {
            plugins: [
              imageminMozjpeg({quality:50,progressive:true}),
              imageminPngquant({ quality: [0.6, 0.8] }),
            ],
          });
        })
        .then((outBuffer) => {
          fs.writeFileSync(destinpathcw, outBuffer);
        })
        .catch((err) => {
          console.log(err);
});

//片段代码,实现上面的异步方法在node的sreeam的流实现

//参考:可以放在流的writeStream.on(“finish”, () =>{ …这里面 })

  let data = groupData[index];

  let inum = 0;
  let error_flag = false;
  //任务处理TODO
  for (let i = 0, len = data.length; i < len; i++) {
    let hairPiece = data[i]["target_path"].split('/');
    let sourcepath = data[i]["path"].replace(/\\/g, "/");
    //let destinpath =  path.join(__pack, 'Model',arg.fatherName,data[i]['name']).replace(/\\/g,'/');
    let destinpath = path.join(__pack, "Model", data[i]["target_path"]);
    let destinpathcw = path.join(__pack, "Model", `${hairPiece[0]}_100x100/${hairPiece[1]}/${hairPiece[2]}`, );
    let readStream = fs.createReadStream(sourcepath);
    let writeStream = fs.createWriteStream(destinpath);
    readStream.pipe(writeStream);
    writeStream.on("finish", () => {
      Promise.promisify(fs.readFile)(sourcepath)
        .then((buffer) => {
          return imagemin.buffer(buffer, {
            plugins: [
              imageminMozjpeg({quality:50,progressive: true}),
              imageminPngquant({ quality: [0.6, 0.8] }),
            ],
          });
        })
        .then((outBuffer) => {
          inum++;
          fs.writeFileSync(destinpathcw, outBuffer);
          // auto_i++;
          // if(arg.id) localStorage.setItem(arg.id, auto_i);
          if (inum == len) {
            if (index < Object.keys(groupData).length - 1) {
              writeFile(arg, ++index, groupData);
              return;
            }
            console.log("complete status");
            //如果任务处理完成,则发送完成通知
            ipcRenderer.removeAllListeners("begain-task");
            ipcRenderer.send("task-complete", arg);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    });
    // 上传出错,将不再继续往下执行其他文件
    writeStream.on("error", (err) => {
      console.log("error", err);
      ipcRenderer.send("error-during-upload", err, arg);
      ipcRenderer.removeAllListeners("begain-task");
      if (!error_flag) ipcRenderer.send("task-complete", arg);
      error_flag = true;
    });
    readStream.on("error", (err) => {
      console.log(err);
      ipcRenderer.send("error-during-upload", err, arg);
      ipcRenderer.removeAllListeners("begain-task");
      if (!error_flag) ipcRenderer.send("task-complete", arg);
      error_flag = true;
    });
    readStream.on("data", (chunk) => {
      currentTotal += chunk.length;
      let res = parseInt((currentTotal / arg.totalSize) * 100);
      if (res != pre_num) {
        ipcRenderer.send("upload-progress", res);
        pre_num = res;
      }
    });
    if (error_flag) break;
  }
}

//遇到的问题

出错

  1. Error: write EOF

at WriteWrap.onWriteComplete [as oncomplete]

解决:

imageminPngquant({ quality: [0.6,0.8] }),

改成这个

imageminPngquant({ quality: 50 }),

官方写着quality的值是Array,实际上改成number就行了


  1. 用imagemin的时候electron打包遇到了:Error: spawn ENOTDIR

这个压缩图片的工具用到了 imagemin这个npm包,在开发的时候压缩图片没任何问题,但是经过electron打包,一旦压缩图片,就会报错,如图所示:

起初我是懵逼的,因为这看不到有效的报错信息啊,但是经过阅读源码网上查找解决方案,最终发现了端倪。在debugger的过程中,发现imagemin是使用二进制可执行文件来对图片进行压缩的,执行二进制的函数是child_process.spawn,这个函数对于文件路径有限制,因为electron打包后,会把依赖项压缩成一个文件,导致这个函数判断路径时报错,对于这个问题,如果是自己的代码中使用了二进制文件,则可以将child_process.spawn替换为child_process.execFile函数来执行二进制文件。

但是我这里引用的是别人的包,如果擅自修改非本源的包,可能会导致项目无法在其他的环境中运行,所以得找例外的解决方案,皇天不负苦心人,终于找到了解决方案,那就是electron打包时,不对依赖项进行压缩,那样就能得到一个正确的路径了。

解决方案
修改package.json中的build选项,这个选项是对electron打包的一系列配置。将其中的 asar 修改为false,就能让electron在打包时,不对依赖进行压缩,如下所示:

“build”: {
“appId”: “com.richard.image_compress”,
“mac”: {
“category”: “tool”
},
“extends”: null,
“files”: [“build”, “*.js”, “public”],
“asar”: false
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值