目前正在做一个文件下载功能。以下是该过程中使用的技术和陷阱的简要总结。上一篇《通过 JavaScript 下载文件到本地(单文件)》讲了如何下载单个文件。本文主要讲一下如何批量下载多个文件,以及如何对多个文件分别进行处理。如果文件数量可控,对下载的文件格式没有要求,可以使用最简单的方法,就是直接遍历文件,为每个下载链接创建一个单文件下载或者iframe下载链接。虽然批量下载zip包可以遍历所有文件,然后批量下载单个文件,但这种体验毕竟不是很好。最常见的方法是批量下载文件并将它们打包成zip。所以第一个实现思路是:在代理服务中,先遍历所有文件请求文件数据,然后将其压缩成zip包,再将zip包返回给客户端。这对于下载数据小的还可以,但是如果批处理文件很大很大,用户要等后台请求完所有的数据打包成压缩包,前端才能有反馈,这可能会耗费时间时间。它很长,用户体验可能很差。同事前期研究的时候说这里可以实现流式下载的能力。大体思路是chunk回包,加上stream式的压缩。......letfileCounter=0;constzippedFilename=encodeURIComponent(downloadData.name);constlist=downloadData.list||[];constheader={'Content-Type':'application/x-zip','Pragma':'public','Expires':'0','Cache-Control':'private,must-revalidate,post-check=0,pre-check=0','Content-disposition':'附件;filename="'+zippedFilename+'"','Transfer-Encoding':'chunked','Content-Transfer-Encoding':'binary'};res.writeHead(200,header);archive.store=true;archive.pipe(res);list.map(item=>{fileCounter++;letinStream=request.get(item.downLoadUrl);letname=item.fileName;letlength=0;inStream.on('response',function(awsData){archive.append(inStream,{name:name});}).on('data',function(data){length+=data.length;}).on('error',function(e){console.error(name+'-error',e);}).on('end',function(endData){fileCounter--;if(fileCounter<1){archive.finalize();}});});archive.on('error',function(err){throwerr;});archive.on('finish',function(err){returnres.end();});......当然,还有一些细节需要处理:比如中文文件名的问题,是否需要限制下载文件的总大小,是否会出现文件做错的情况不存在等
