开始
- 最近代码重构遇到了一个问题,需要把
OSS
上的一批图片打包下载 - 旧服务器的硬盘是直接挂载
OSS
,所以直接调的Linux
系统命令复制打包,所以速度比较快。新服务器重构代码行不通,这样做也不好 - 查阅
OSS
并没有提供相关API
(七牛支持)
解决方法:
- PASS掉
PHP
后台fetch
图片到内存然后进行打包输出给前端(图片有ai
,psd
内存撑不住) - PASS掉
PHP
后台fetch
图片到服务器硬盘,然后进行打包输出一个临时链接给前端(同上,文件太大,导致fetch
时间和打包的时间太久) - JS 尝试通过前端请求后端,后端返回文件信息,然后前端异步请求所有文件,最后在前端打包下载
前提
想法很好,并且已经有人这样做了,我们只用考虑按照别人的做法坐下去
前端打包有两个前提:
1. 跨域问题,需要运维在OSS
或者下载的资源服务器设置允许跨域
2. CDN
问题,让运维配置一个新域名不要走CDN
(如没使用CDN
可忽略)
步骤
- 使用https://github.com/Stuk/jszip这个库打包文件
- 使用https://github.com/Stuk/jszip-utils获取远程数据(直接通过
AJAX
获取,需要转换格式) - 直接下载这两个库,然后把
dist/
下的文件放入到项目,也可以用github
提供的方式引入 - 部分逻辑代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
// 引入文件 <script type="text/javascript" src="/xxx/jszip.min.js"></script> <script type="text/javascript" src="/xxx/jszip-utils.min.js"></script> <!--[if IE]> <script type="text/javascript" src="/xxx/jszip-utils-ie.min.js"></script> <![endif]--> <script> let total = 0; let progress = 0; // 可通过按钮或者其它事件触发 $.get('/urls', function(res) { // 假设 res.data 是后端返回的一组远程数据对象 // {url: 'x.jpg', filename: 'xx.jpg', path: 'xxxx'} total = res.data.length; if (total === 0) { console.error('图集无图片可下载'); return; } let zip = new JSZip(); // map 存储 folder 对象 let folderMap = {}; // 遍历所有后端返回的 urls res.data.map(function (data) { // 获取远程资源数据 JSZipUtils.getBinaryContent( data.url, function (err, binData) { ++ progress; if (err && progress < total) { console.log(err); return; } // 第一次实例化 folder 对象 if (! folderMap[data.path]) { folderMap[data.path] = zip.folder(data.path); } let pf = folderMap[data.path]; // 第三个参数必须设置,否则下载的文件将产生错误 pf.file(data.filename, binData, {binary: true}); if (progress === total) { console.log('请稍等,数据打包中'); zip.generateAsync({type:"blob"}).then(function(content) { // 下载文件 const link = document.createElement('a'); link.href = window.URL.createObjectURL(content); link.download = 'data.zip'; link.click(); document.body.removeChild(link); }); } } ); }) }) </script> |
完成之后,发现效果还不错。速度也比后端的来的块。毕竟不经过后端。而且可以多个请求异步处理。