油猴Tampermonkey脚本-纯js实现图片打包下载

在前一篇文章的最后(强大的油猴Tampermonkey脚本开发环境搭建),我提到了我练手的时候开发了一个Instagram图片批量下载脚本,但是当时这个脚本我说是有缺陷的,批量图片下载貌似最多只能12个任务同时下载,也就是最多只能下载12张图片。

我就在找寻,是否存在一种方法,可以将这些图片仅通过前端就可以进行打包成为.zip文件,然后下载一个压缩包。

后面我就找到了一个jszip库,使用它就可以实现在前端打包文件进行下载。

来看看最终效果:

script

1. 正文

jszip这个库使用起来是非常方便的,也非常简单。

import JSZip from "jszip";
import { saveAs } from 'file-saver';

const zip = new JSZip();

// 创建一个名为images的文件夹
const img = zip.folder("images");
// 3个参数分别是文件名、图片的base64编码、和base64验证
img.file("smile.gif", imgData, {base64: true});

zip.generateAsync({type:"blob"}).then(function(content) {
    // 使用FileSaver.js下载到本地
    saveAs(content, "example.zip");
});

就是这么简单,一般来说网页上面的图片都是url形式的,那么如何将url转为base64呢?其实直接使用canvas就可以转换,代码如下所示。

/**
 * 转一张图片编码
 * @param {string} imgUrl 图片url
 * @return {Promise<string>}
 */
function getBase64(imgUrl) {
  return new Promise((resolve) => {
    const image = new Image();
    image.crossOrigin = ""; // 解决跨域问题
    image.src = imgUrl;
    image.onload = function () {
      let canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      let context = canvas.getContext("2d");
      context.drawImage(image, 0, 0, image.width, image.height);
      // 得到图片的base64编码数据
      resolve(canvas.toDataURL("image/png", 1).split(",")[1]);
    };
  });
}

因为该函数为异步函数,所以需要使用Promise.all()或者配合async、await进行使用。

2. 脚本编写遇到的坑

2.1 async、await不能用

因为getBase64()函数为异步函数,所以要等待全部的图片都转为了base64,然后再添加到jszip进行压缩,如果不处理该异步问题,最后压缩出来的内容为空,没有图片。

最开始async、await无法使用,导致我使用了Promise.all(),最后发现使用Promise.all()的话制作进度条时不好处理,找了很多文章发现异常的麻烦,于是转头开始调查为什么async、await无法使用,最后发现需要安装下面的包:

npm i regenerator-runtime -D

该包貌似是专门处理async、await在ES5中的兼容性问题。

2.2 图片打包时报错

因为canvas转换出来会加上data:image/png;base64,这一段,所以会报Error: Invalid base64 input, it looks like a data url.这个错误,所以使用.split(",")[1]将前面的那段去掉就好了。

3. 最后

最后不得不惊叹油猴脚本的厉害之处,可以通过JavaScript将任意内容嵌入到网页中。