使用jszip和file-saver导出图片,并打包为zip:
import JSZip from "jszip";
import FileSaver from "file-saver";
一,jszip解压缩
使用loadAsync,zipFile为压缩包,下面的例子表示读取zip中的result.txt文件,输出内容。
const jszip = new JSZip()
jszip.loadAsync(zipFile).then((zip) => {zip.files["result.txt"].async("string").then(function (con) {console.log(con)});
})
二、jszip压缩
先搞个简单的压缩:使用jszip创建一个名为image.zip的压缩包,其中包含一个文本文档和一个文件夹。
zip.file("hello.txt", 'hello world');
zip.folder('testfolder');
zip.generateAsync({ type: "blob" }).then(function (content) {FileSaver.saveAs(content, "images.zip");
});
再搞个文件夹包含文本文档的压缩:使用jszip创建一个名为image.zip的压缩包,其中包含一个testfolder文件夹,文件夹包含一个名为test.txt的文本文档。
zip.folder("testfolder").file('test.txt', '啦啦啦啦啦啦');
zip.generateAsync({ type: "blob" }).then(function (content) {FileSaver.saveAs(content, "images.zip");
});
最后试着创建有规律的压缩包:使用jszip创建一个名为image.zip的压缩包,其中包含五个文件夹,每个文件夹包含20个文本文档,每个文本文档的名称是各自的序号,文档内容是各自的文件名去掉后缀,文件夹的名称是各自包含的起止文件序号,例如在名为1-20的文件夹中包含1.txt、2.txt、3.txt……20.txt
for (let i = 0; i < 5; i++) {let begin = i * 20 + 1;let end = (i + 1) * 20;let img = zip.folder("photos" + begin + "-" + end);for (let j = 0; j < 20; j++) {img.file(i * 20 + j + '.txt', i * 20 + j + '');}
}
zip.generateAsync({ type: "blob" }).then(function (content) {FileSaver.saveAs(content, "images.zip");
});
三、实现导出图片zip
1、获取图片url
目前只遇到过两种情况:
- 通过dom获取,例如 卡片+多选按钮组 方式的展示形式,勾选导出,此时可根据dom获取url;
- 通过接口获取;
总之能拿到有效url即可。
downLoad(amount) {let url2 = ''; // 照片let self = this;Axios.get(url2).then((res) => {let arr = [];for (let i = 0, len1 = res.data.length; i < len1; i++) {if (res.data[i].pictureUrl !== '') {arr.push(res.data[i])}}let result = [];for (let i = 0, len2 = arr.length; i < len2; i += 20) {result.push(arr.slice(i, i + 20));}self.packageImages(result)}).catch((err) => {console.log(err);})
}
2、判断图片地址是否有效
只下载有效图片,所以需要验证图片是否有效:大小不应为0,宽高不应为0。
async validateImage(pathImg) { // 验证图片地址是否有效var ImgObj = new Image();ImgObj.src = pathImg;return ImgObj.fileSize > 0 || (ImgObj.width > 0 && ImgObj.height > 0);
}
3、图片转base64
需要转为base64,以供后续保存图片。
getBase64(img) {function getBase64Image(img, width, height) {// width、height调用时传入具体像素值,控制大小 ,不传则默认图像大小let canvas = document.createElement("canvas");canvas.width = width || img.width;canvas.height = height || img.height;let ctx = canvas.getContext("2d");ctx.drawImage(img, 0, 0, canvas.width, canvas.height);let dataURL = canvas.toDataURL();return dataURL;}let image = new Image();image.crossOrigin = 'Anonymous';image.src = img;let deferred = $.Deferred();if (img) {image.onload = function () {deferred.resolve(getBase64Image(image));};return deferred.promise();}
}
4、打包下载
这里是每20张图片分一个目录,如果不需要分目录就不用将得到的图片拆成二维数组,直接打包就好。
packageImages(arr, index) {let self = this;let imgs = [];for (let i = 0; i < arr.length; i++) {for (let j = 0; j < arr[i].length; j++) {if (!arr[i][j].pictureUrl.match('base64,')) {imgs.push(arr[i][j]);}}}let imgBase64 = [];let imgsName = [];let imageSuffix = [];// 图片后缀let zip = new JSZip();for (let j = 0; j < imgs.length; j++) {let suffix = ".jpg";imageSuffix.push(suffix);this.getBase64(imgs[j].pictureUrl).then(function (base64) {imgBase64.push(base64.substring(22));let fileName = imgs[j].cardId;imgsName.push(fileName);}, function (err) {console.log(err);});}function tt() {setTimeout(function () {if (imgs.length === imgBase64.length) {for (let i = 0; i < arr.length; i++) {let begin = i * 20 + 1;let end = 0;if (arr[i].length < 20) {end = imgsName.length;} else {end = (i + 1) * 20}let img = zip.folder("photos" + begin + "-" + end);for (let j = 0; j < arr[i].length; j++) {img.file(imgsName[i * 20 + j].trim() + imageSuffix[i * 20 + j], imgBase64[i * 20 + j], {base64: true});}}zip.generateAsync({type: "blob"}).then(function(content) {FileSaver.saveAs(content, "images.zip");});} else {tt();}}, 100);}tt();
}
数据太多时下载时间很长,那页面等待时间也会很长,可以加上进度条,每20个打个包下载一个zip,更新进度条。
总结
本篇实践了jszip的压缩与解压缩,使用jszip和file-saver新建了包含文本文档、图片、文件夹的压缩包,实现了分段打包。共勉!