当前位置: 首页 > 面试题库 >

在WebApp中创建和下载巨大的ZIP(从多个BLOB)的最佳实践

皇甫伟彦
2023-03-14
问题内容

我将需要从Web应用程序中下载大量文件。

显然,这将是一项长期运行的操作( 每年[每个客户] 使用 一次
),因此时间不是问题(除非遇到一些超时,但是我可以通过创建某种形式的Keepalive心跳)。我知道如何创建一个隐藏的 iframe
并使用它content-disposition: attachment来尝试下载文件,而不是在浏览器中打开它,以及如何为绘制进度表而建立客户端与服务器之间的通信;

下载的实际大小(和文件数)是未知的,但是为简单起见,我们可以将其实际上视为1GB,由100个文件组成,每个文件10MB。

由于这应该是一次单击操作,因此我首先想到的是将所有文件分组,同时从数据库中读取它们,并以动态生成的ZIP形式进行存储,然后要求用户保存ZIP。

问题是: 从WebApp中的多个小字节数组创建大型存档时,最佳实践是什么?已知的缺点和陷阱是什么?

可以随机分为:

  • 应该将每个字节数组转换为物理临时文件,还是可以将它们添加到内存中的ZIP中?
  • 如果是,我知道我必须处理名称的可能相等(它们可以在数据库的不同记录中具有相同的名称,但不能在同一文件系统或ZIP中):还有其他可能的问题吗?介意(假设文件系统始终具有足够的物理空间)?
  • 由于我不能依靠足够的RAM来执行内存中的全部操作,因此我猜应该先将ZIP创建并馈送到文件系统,然后再发送给用户。有什么方法可以做不同的事情(例如,使用 websocket ),例如询问用户将文件保存在何处,然后启动从服务器到客户端的恒定数据流(我猜是 科幻 )?
  • 您会想到的任何其他相关已知问题或最佳做法将不胜感激。

问题答案:

对于无法立即放入内存的大型内容,请将内容从数据库 流式传输 到响应。

这种事情实际上很简单。您不需要AJAX或websocket,可以通过用户单击的简单链接来流式传输大文件下载。而且现代的浏览器都有不错的下载管理器,它们都有自己的进度条-
为什么要重新发明轮子?

如果为此从头开始编写servlet,请访问数据库BLOB,获取其输入流,然后将内容复制到HTTP响应输出流。如果您具有Apache Commons
IO库,则可以使用IOUtils.copy(),否则您可以自己执行此操作。

可以使用ZipOutputStream快速创建ZIP文件。在响应输出流上(从servlet或框架提供的任何内容)创建一个,然后从数据库中获取每个BLOB,putNextEntry()首先使用,然后如前所述对每个BLOB进行流式处理。

潜在的陷阱/问题:

  • 根据下载大小和网络速度,请求可能需要很多时间才能完成。防火墙等可以阻止这种情况并尽早终止请求。
  • 希望您的用户在请求这些文件时处于良好的公司网络中。如果是远程/躲闪/移动连接,情况会更糟(如果下载了2.0G的1.9G后掉线了,用户必须重新启动)。
  • 它可能会给您的服务器带来一些负担,尤其是压缩巨大的ZIP文件时。ZipOutputStream如果这是一个问题,则可能值得在创建时关闭/关闭压缩功能。
  • 2GB以上(或4 GB)的ZIP文件可能与某些ZIP程序有关。我认为最新的Java 7使用ZIP64扩展,因此此版本的Java将正确编写巨大的ZIP,但是客户端是否将具有支持大zip文件的程序?我以前肯定遇到过这些问题,尤其是在旧的Solaris服务器上


 类似资料:
  • 谷歌云功能的运作方式似乎是: 你的模块进入一个目录 这很奇怪,因为: 即使模块<代码>一个。js和两个。js在运行时需要不同的包,即共享的意味着它们的启动时间将比单独启动慢,因为它们都需要安装包的所有依赖项,而不仅仅是它们自己的 因此,确保云功能以尽可能轻的运行时占用空间以最佳方式运行的最佳实践是什么?谷歌的设计决策似乎意味着,你做的云功能越多,那么每个云功能中捆绑的垃圾就越多,速度越慢,成本也越

  • 我试图通过在本地服务器上创建zip文件来下载a 2文件。文件是以zip格式下载的,但当我试图解压缩它时。它给出了一个错误:找不到中央目录签名的结尾。要么该文件不是zip文件,要么它构成了多部分存档的一个磁盘。在后一种情况下,中心目录和zip文件注释将在该存档的最后一个磁盘上找到。 下面的代码我使用这个: 我检查了传递到函数中的所有变量的值,都很好。所以请看这个。提前谢谢。

  • 问题内容: 当我通过创建zip存档时,是否可以将生成的存档拆分为多个卷? 假设我的整体存档中有个,我想将其拆分为3个文件,每个文件限制为10 MB。 是否有具有此功能的zip API?或任何其他好的方法来实现这一目标? 谢谢Thollsten 问题答案: 检查:http : //saloon.javaranch.com/cgi- bin/ubb/ultimatebb.cgi?ubb=get_top

  • 问题内容: 今天,我在登录表单后面添加了额外的安全检查,以减缓暴力攻击。我有多个登录表单,并提供了一个易于调用的函数,该函数可以进行所有检查,然后返回结果。 问题是结果不是单个值,结果包括: 为此,我创建了一个新类。这一切都很好。 但是我经常有方便的实用程序函数,这些函数会返回多个值,并开始发现每次为结果创建一个新类都有些烦人。 有没有更好的方法来返回多个值?还是我只是懒惰?:) 问题答案: 不,

  • 我想为大量数据(如整数)创建数组。这个数组将是2D矩阵的表示。< br >我不能使用STL,因为它将与CUDA一起运行。< br >我想知道以下选项的利弊: int arr[SIZE]-这是创建数组的最简单方法。它在堆栈上分配,因此它将是最快的-这里的问题是大小非常有限。 int*arr=new int[SIZE] int**arr=new int*[DIM1]-如果我们考虑效率,这是最坏的情况,

  • 当我需要在Vertx中创建新的垂直线时,有人能给我提供最佳实践吗。我知道,每个垂直节点都可以远程部署并放入集群。然而,我仍然有一个问题,如何设计我的应用程序。那么我的问题是: 有很多垂直线可以吗 例如,我可以将vertx作为参数传递到每个endpoint,并使用它来创建路由器: