文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

下载文件并使用Javascript将其压缩在浏览器中

2024-12-11 20:19

关注

我最近从事一个副项目,该项目可根据用户的请求生成报告。对于每个请求,我们的后端将生成一个报告,将其上传到Amazon S3存储,然后将其URL返回给客户端。由于生成报告需要一些时间,因此将存储输出文件,并且服务器将通过请求参数来缓存其URL。如果用户订购相同的商品,则后端将返回现有文件的URL。

几天前,我有一个新要求,我需要下载一个包含数百个报告的zip文件,而不是单个文件。我想到的第一个解决方案是:

但是此解决方案有一些缺点:

我想出的最终解决方案是:将所有文件下载到浏览器中,然后将其压缩。在这篇文章中,我将介绍如何做。

免责声明:在这篇文章中,我假设你已经具有有关Javascript和Promise的基本知识。如果你没有,我建议你先了解他们,然后再回到这里:)

下载单个文件

在应用新解决方案之前,我的系统允许下载一个报告文件。有很多方法可以做到这一点,后端可以直接通过HTTP请求响应原始文件的内容,也可以将文件上传到另一个存储设备并返回文件URL。我选择第二种方法,因为我想缓存所有生成的文件。

一旦有了文件URL,在客户端上的工作就非常简单:在新选项卡中打开此URL。浏览器将完成剩下的工作以下载文件。

  1. const downloadViaBrowser = url => { 
  2.     window.open(url, ‘_blank’); 

下载多个文件并存储在内存中

当下载和压缩多个文件时,我们不能再使用上面的简单方法。

解决此问题的另一种方法是使用 fetch 来下载文件并将数据作为Blob存储在内存中。然后,我们可以将其写入文件或将这些Blob数据合并为zip文件。

  1. const download = url => { 
  2.   return fetch(url).then(resp => resp.blob()); 
  3. }; 

这个函数返回一个被解析为blob的promise。我们可以结合 Promise.all() 来下载多个文件。Promise.all() 将一次性完成所有的promise,如果所有的子promise都被解析,或者其中一个承诺出现错误,则进行解析。

  1. const downloadMany = urls => { 
  2.   return Promise.all(urls.map(url => download(url)) 

按X文件组下载

但是,如果我们需要一次下载大量文件怎么办?假设有1000个文件?使用 Promise.all() 可能不再是一个好主意,你的代码将一次发送一千个请求。 这种方法有很多问题:

我考虑过的解决方案是将文件分成多个组。假设我有1000个文件可供下载。而不是通过 Promise.all() 立即开始一次下载所有文件,我将每次下载5个文件。在完成这5个之后,我将开始另一个包,我总共会下载250个包。

要实现这个功能,我们可以做一个自定义逻辑。或者我建议一个更简单的方法,就是利用第三方库bluebirdjs。该库实现了许多有用的Promise函数。在这个用例中,我将使用 Promise.map()。注意这里的Promise现在是库提供的自定义Promise,而不是内置的Promise。

  1. import Promise from 'bluebird'; 
  2. const downloadByGroup = (urls, files_per_group=5) => { 
  3.   return Promise.map( 
  4.     urls,  
  5.     async url => { 
  6.       return await download(url); 
  7.     }, 
  8.     {concurrency: files_per_group} 
  9.   ); 

通过上面的实现,该函数将接收一个URL数组并开始下载所有URL,每次都具有最大 files_per_group。该函数返回一个Promise,它将在下载所有URL时解析,并在其中任何一个失败时拒绝。

创建zip文件

现在我已经把所有的内容都下载到内存中了。正如我上面提到的,下载的内容被存储为Blob。下一步是使用这些Blob数据创建一个压缩文件。

  1. import JsZip from 'jszip'; 
  2. import FileSaver from 'file-saver'; 
  3. const exportZip = blobs => { 
  4.   const zip = JsZip(); 
  5.   blobs.forEach((blob, i) => { 
  6.     zip.file(`file-${i}.csv`, blob); 
  7.   }); 
  8.   zip.generateAsync({type: 'blob'}).then(zipFile => { 
  9.     const currentDate = new Date().getTime(); 
  10.     const fileName = `combined-${currentDate}.zip`; 
  11.     return FileSaver.saveAs(zipFile, fileName); 
  12.   }); 

最终代码

让我们在这里完成我为此完成的所有代码。

  1. import Promise from 'bluebird'; 
  2. import JsZip from 'jszip'; 
  3. import FileSaver from 'file-saver'; 
  4. const download = url => { 
  5.   return fetch(url).then(resp => resp.blob()); 
  6. }; 
  7. const downloadByGroup = (urls, files_per_group=5) => { 
  8.   return Promise.map( 
  9.     urls,  
  10.     async url => { 
  11.       return await download(url); 
  12.     }, 
  13.     {concurrency: files_per_group} 
  14.   ); 
  15. const exportZip = blobs => { 
  16.   const zip = JsZip(); 
  17.   blobs.forEach((blob, i) => { 
  18.     zip.file(`file-${i}.csv`, blob); 
  19.   }); 
  20.   zip.generateAsync({type: 'blob'}).then(zipFile => { 
  21.     const currentDate = new Date().getTime(); 
  22.     const fileName = `combined-${currentDate}.zip`; 
  23.     return FileSaver.saveAs(zipFile, fileName); 
  24.   }); 
  25. const downloadAndZip = urls => { 
  26.   return downloadByGroup(urls, 5).then(exportZip); 

总结

利用客户端的功能有时对于减少后端的工作量和复杂性非常有用。

不要一次发送大量的请求。你会在前端和后端都遇到麻烦。相反,将作品分成小块。

介绍一些第三方库bluebird,jszip和file-saver。他们为我工作得很好,也可能对您有帮助。

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯