一次基于electron的图片上传插件的开发过程

2020-06-18  本文已影响0人  千茉紫依
背景:

项目前端有个图片压缩包上传功能,用户上传的时候会选择单反拍摄的巨幅图片,由于前端打不开压缩包,也没法读取压缩率并重新编码,只能原样发送,这给后台存储造成相当大的压力.同时由于压缩包内容涉及隐私,所以需要制作专门的加密压缩工具,使压缩包无法用通用的压缩工具打开.由于同组的C++同事都在忙别的项目,这个工具就由我来开发了.

预期功能点:
选型:

下面是最终的成品: 耗时两天完成


工具界面
详细流程:
渲染进程
<template>
     <button class="btn"
                @click="showModalHandler">选择要压缩的文件夹</button>
</template>

<script>
export default {
  methods: {
    showModalHandler() {
      ipcRenderer.send("open-directory-dialog", {
        openMethod: "openDirectory",  // 参数openDirectory为打开文件夹,参数openFile为打开文件
      });
    },
</script>
主进程
ipcMain.on('open-directory-dialog', function (event, compressOpt) {
    dialog.showOpenDialog({
        properties: [compressOpt.openMethod] 
    }, function (files) {
        if (files) {// 如果有选中
            // 发送选择的对象给子进程, files[0]是打开的文件绝对路径
            // console.log("path", files[0]);
            // TODO 文件操作,压缩打包
            event.sender.send('selectedItem', files[0])
        }
    })
});

  1. 路径是否存在: fs.existsSync(path)
  2. 文件信息: info = fs.statSync(path)
  3. 是目录:info.isDirectory()
  4. 是文件:info.isFile()
  5. 新建文件夹:fs.mkdirSync(path)
  6. 删除空文件夹,必须为空才能删除:fs.rmdirSync(path)
  7. 创建文件:fs.writeFileSync(filename,arraybuffer)
  8. 删除文件:fs.unlinkSync(path)
  9. 读取文件:content =fs.readFileSync(filePath)
  10. 打开文件夹,使用cmd调用explorer.exe:
const exec = require('child_process').exec
exec(`explorer.exe /e, /root,${dirPath}`)
  1. 删除目录代码(目录有文件也能删除)
function delPath(path) {
    if (!fs.existsSync(path)) {
        console.log("路径不存在");
        return "路径不存在";
    }
    var info = fs.statSync(path);
    if (info.isDirectory()) {//目录
        var data = fs.readdirSync(path);
        if (data.length > 0) {
            for (var i = 0; i < data.length; i++) {
                delPath(`${path}/${data[i]}`); //使用递归
                if (i == data.length - 1) { //删了目录里的内容就删掉这个目录
                    delPath(`${path}`);
                }
            }
        } else {
            fs.rmdirSync(path);//删除空目录
        }
    } else if (info.isFile()) {
        fs.unlinkSync(path);//删除文件
    }
}
  const JPGBuffer = fs.readFileSync(JPGPath);
  testJPGHeader(JPGBuffer)

  function testJPGHeader(JPGBuffer) {
        const JPGHeader = JPGBuffer.slice(0, 3);
        const HT_STD_HEADER = [0xff, 0xd8, 0xff];
        let notJPG = false;
        JPGHeader.forEach((v, i) => {
            if (HT_STD_HEADER[i] !== v) notJPG = true;
        });
        return notJPG;
    }
监听函数被反复注册,造成失败消息被重复发送.jpg
html:
 <button class="btn"
              @click="showModalHandler">选择要打包的文件夹</button>

js:
 showModalHandler() {
    const that = this;
    this.init();
    //取消失败消息监听,避免反复注册
    ipcRenderer.removeAllListeners("extension-error");
    //发送打开目录消息
    ipcRenderer.send("open-directory-dialog", {
      openMethod: "openDirectory",
      compress: this.compress
    });
     //打开文件消息
    ipcRenderer.once("selectedItem", function(e, path) {
      console.log("selectedItem", path);
      that.loading = true;
    });
     //完成压缩消息
    ipcRenderer.once("patchZip-Done", function(e, zipName) {
      console.log("zipName", zipName);
      if (zipName === "error") {
        that.zipFill = true;
      }
      that.loading = false;
    });
    //完成压缩消息
    ipcRenderer.on("extension-error", function(e, filename) {
      console.log("extension-error-filename", filename);
      that.errfiles.push(filename);
    });
  },
    getPixels(fileAbPath, function (err, pixels) {
        if (err) {
            return
        }
        let compressRio = 0.9;
        let [imageWidth, imageHeight] = pixels.shape
         //找到比较小的边
        let loopVar = imageWidth > imageHeight ? imageHeight : imageWidth;
        while (loopVar >= 480) {
            loopVar = loopVar * compressRio;
            imageWidth = imageWidth * compressRio;
            imageHeight = imageHeight * compressRio;
        }
        imageWidth = Math.floor(imageWidth)
        imageHeight = Math.floor(imageHeight)
        const content = pixels.data
        fs.writeFile(outPath, content, async function (err) {
            const options = {
                images: [outPath],
                width: imageWidth,
                height: imageHeight,
                quality: 85
            };
            // 执行压缩.
            await resizeOptimizeImages(options);
        });
    })
上一篇下一篇

猜你喜欢

热点阅读