来了,前端一键下载压缩包
本文最后更新于:2022年7月6日 上午
什么?你想一键下载图片压缩包
前提
什么?你想一键下载图片压缩包?这还真的是我接到需求后的第一句话。产品想把商品相册中的图片以压缩包的形式下载下来,于是我张口就来:后端开个接口呗。。。
一番调研之后,确认这个需求完全可以由前端独立实现,具体依赖以下两个库:
实现思路
- 首先利用
Image
下载图片,然后用canvas
将图片导出base64
形式 JSZip
创建文件夹,并将上一步获得的图片数据进行打包- 打包之后,使用
FileSaver
将打包好的zip
保存到本地
具体代码
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
export default (urls, zipName = '素材包') => {
return new Promise((resolve, reject) => {
const zip = new JSZip();
// 创建文件夹
const imgFolder = zip.folder(zipName);
const imagePromises = urls.map((src) => getBase64Image(src));
Promise.all(imagePromises)
.then((results) => results.filter((result) => result.length > 0))
.then((base64Images) => {
console.table(base64Images);
if (base64Images.length === 0) {
reject();
return;
}
for (let i = 0; i < base64Images.length; i++) {
let base64Image = base64Images[i];
// 去掉 bas64, 标志
base64Image = base64Image.split('base64,')[1];
// 添加文件到 folder 中
imgFolder.file(`${i}.png`, base64Image, { base64: true });
}
// 打包
zip
.generateAsync({ type: 'blob' })
.then((blob) => {
// 导出下载
saveAs(blob, `${zipName}.zip`);
resolve();
})
.catch(() => {
reject();
});
});
});
};
function getBase64Image(src, width, height) {
return new Promise((resolve) => {
const image = new Image();
image.crossOrigin = ''; // 设置跨域
image.src = src;
image.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = width || image.width;
canvas.height = height || image.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL()); // 导出 base64
};
image.onerror = () => {
console.log(`图片 ${src} 加载失败...`);
resolve('');
};
});
}
特别要注意一下这句代码:
image.crossOrigin = ''; // 设置跨域
如果不设置的话,则 canvas
会报错:
Failed to execute ‘toDataURL’ on ’HTMLCanvasElement’: Tainted canvased may not be exported
H5 中,部分元素提供了支持 CORS
的属性,这些元素包括 <img>
,<video>
,<script>
等,对应的属性名即 crossOrigin
:
属性值 | 描述 |
---|---|
use-credentials | 元素的跨域资源请求需要凭证标志设置 |
anonymous | 元素的跨域资源请求不需要凭证标志设置 |
我们这里虽然设置了 image.crossOrigin
为空字符串,但实际生效的是 anonymous
,更详细的内容的可参考张鑫旭的解决 canvas 图片 getImageData,toDataURL 跨域问题这篇文章,我就不多说了。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!