甲方客户甩来一个需求,需求把用户上传的视频、图片打包成zip并下载下来,而且要遵循一定的目录结构。原本需求定为后端实现,但经过后端同学调研了一波,发现会严重消耗后端的功用、带宽,遂低微(niubi)前端上岗上线解决问题。
在谷歌、必应、百度…上调研了一波前端技能实现,大致找到两种解决方案,一是jszip + file-saver,二是streamSaver,下面介绍下这两种技能的运用。
jszip + file-saver
下载插件,随便附上github地址
jszip:github.com/Stuk/jszip
file-saver:github.com/eligrey/Fil…
npm install jszip file-saver
jszip + file-saver 运用方法比较简单,如下即可实现资源打包下载:
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
(async() => {
// 初始化一个zip打包目标
const zip = new JSZip();
// 创建一个名为images的新的文件目录
const folder = zip.folder('images');
// 恳求远程资源的blob,其他文件,比方视频、表格等也是一样的
const blob = await fetch('').then(response => response.blob())
// 文件夹添加资源,图片也支撑base64类型 {base64: true}
folder.file('test.png', blob, { Blob: true });
// 把打包内容异步转成blob二进制格局
zip.generateAsync({type:"blob"}).then((content) => {
// 下载压缩包
saveAs(content, 'example.zip');
});
})()
不过该方法有比较明显的缺点,主要在兼容性及资源的体积上,在谷歌浏览器上能到达 2GB,但在其他浏览器上一般只支撑到几百 MB,可参考下面的file-saver浏览器支撑介绍:
所以,为了统筹非谷歌浏览器的用户,还需求进一步地探究新的技能解决方案,也能够结合本公司对前端兼容性的要求来权衡。
streamSaver
streamSaver 的运用会略微费事一点,不过依照官方的运用示例,也比较容易跑起来。
下载插件
npm install streamsaver
此外,还需求从github上下载几个文件到项目目录,分别是:
mitm.html:github.com/jimmywartin…
sw.js:github.com/jimmywartin…
zip-stream.js:github.com/jimmywartin…
streamSaver 的运用方法如下:
import streamSaver from 'streamsaver';
// gihub上下载的zip-stream.js
import '@/libs/streamsaver/zip-stream';
// mitm.html的存放目录,sw.js同级存放,都需求跟从项目部署到服务器
streamSaver.mitm = `${location.origin}/libs/streamsaver/mitm.html`;
// 初始化打包目标
const readableZipStream = new window.ZIP({
async pull(ctrl) {
// 恳求资源 & 设置目录
const res = await fetch('');
const stream = () => res.body;
const name = '/images/test.png';
// 添加到处理队列,可遍历添加
ctrl.enqueue({ name, stream });
ctrl.close();
},
});
// 资源命名
const fileStream = streamSaver.createWriteStream('example.zip');
// more optimized
if (window.WritableStream && readableZipStream.pipeTo) {
return readableZipStream
.pipeTo(fileStream)
.then(() => {
console.log('下载成功')
})
.catch((error) => {
console.error('下载失利', error);
})
}
// less optimized
const writer = fileStream.getWriter();
const reader = readableZipStream.getReader();
const pump = () =>
reader
.read()
.then(() => {
console.log('下载成功')
})
.catch((error) => {
console.error('下载失利', error);
})
pump();
经过简单的测验发现,streamSaver 的兼容性更佳,在一些非谷歌浏览器上,也能到达 2GB体积的下载,所以也是目前实现需求的首选方案。
其实上面两种技能方案具有不止本文介绍的一些功用,还具有其他强大的功用,感兴趣的同学能够去探究下。
其他注意事项
- 不同的浏览器支撑度不一样,需求多测验,而且考虑客户的承受程度;
- streamSaver 在本地因为证书问题,无法正常下载资源,可发布到测验服务器再验证;
- 资源跨过问题需求自行解决。
本文正在参加「金石方案 . 分割6万现金大奖」