V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
DavidNineRoc
V2EX  ›  问与答

远程 URL 文件批量下载打包的方法

  •  
  •   DavidNineRoc · 2020-04-23 18:53:12 +08:00 · 624 次点击
    这是一个创建于 1436 天前的主题,其中的信息可能已经有所发展或是发生改变。

    开始

    • 最近代码重构遇到了一个问题,需要把OSS 上的一批图片打包下载
    • 旧服务器的硬盘是直接挂载OSS,所以直接调的Linux系统命令复制打包,所以速度比较快。新服务器重构代码行不通,这样做也不好
    • 查阅OSS并没有提供相关API(七牛支持)

    解决方法:

    • PASS 掉 PHP后台fetch图片到内存然后进行打包输出给前端(图片有ai,psd内存撑不住)
    • PASS 掉 PHP后台fetch图片到服务器硬盘,然后进行打包输出一个临时链接给前端(同上,文件太大,导致fetch时间和打包的时间太久)
    • JS 尝试通过前端请求后端,后端返回文件信息,然后前端异步请求所有文件,最后在前端打包下载

    前提

    想法很好,并且已经有人这样做了,我们只用考虑按照别人的做法坐下去 前端打包有两个前提:

    1. 跨域问题,需要运维在OSS或者下载的资源服务器设置允许跨域
    2. CDN问题,让运维配置一个新域名不要走CDN(如没使用CDN可忽略)

    步骤

    // 引入文件
    <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>
    

    完成之后,发现效果还不错。速度也比后端的来的块。毕竟不经过后端。而且可以多个请求异步处理。

    原文地址: http://www.shiguopeng.cn/archives/442

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2798 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:47 · PVG 22:47 · LAX 07:47 · JFK 10:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.