我正在创建一个ZIP文件。我正在使用dotnetzip来执行此操作。 我的ZIP文件大小最多可达500 MB,许多用户同时尝试下载它。
我提供文件的最有效方式是什么?如果给出了选择,我宁愿不将文件保存在磁盘上,因为这可能会导致严重的磁盘空间限制。
编辑:有关我的用例的更多信息:
我们将文件托管在Intranet网站中托管的SharePoint 2010资产库中,该网站遍布全球。文件通常为10-80 MB。用户希望能够一次下载多个文件。
答案 0 :(得分:2)
嗯,理论上 :
对于传统的ASP.Net应用程序,您应该只能将响应数据(字节)写入HttpContext.Response.OutputStream
(如何获取http响应上下文将取决于您如何处理下载请求,例如,如果您正在实现IHttpHandler
然后你得到传递给你的http上下文。)
看看DotNetZip示例,Save
方法看起来像一个流,所以这就像
zip.Save(context.Response.OutputStream);
如果zip文件被许多用户重复使用和下载,那么您可以在创建zip时将zip写入MemoryStream
,以便稍后将此内存流的内容复制到各个响应中:
MemoryStream stream = new MemoryStream()
zip.Save(stream);
// Save data somewhere common (e.g. cache it)
byte[] data = stream.ToArray();
将此数据写回响应:
MemoryStream reader = new MemoryStream(data);
CopyStream(reader, context.Response.OutputStream);
有关CopyStream的实现,请参阅Best way to copy between two Stream instances - C#。
然而在现实中:
考虑到这一点,这意味着如果zip文件是500MB,我们在内存中存储500MB的数据 - 如果这是唯一存在的zip文件但是如果有3或4个这些我们很快就会耗尽“内存”(即虚拟地址空间)。
解决方案?我担心最简单的方法是将zip保存到文件中(即使它是一个不是由IIS直接提供的临时文件)而不是内存流:
// To save the zip
string filename = Path.GetTempFileName();
zip.Save(filename);
// To write the file
context.Response.TransmitFile(filename);
完成后,您也应该删除该文件。
请注意,如果您决定在多个用户之间共享相同的zip,则只需要打扰它 - 如果您只是按用户构建zip并使用{{1}将其直接写入输出流那么事情就不那么麻烦了。我的建议是首先以简单的方式进行操作然后进行测试,看看是否只能通过创建一次zip来解决性能问题。
答案 1 :(得分:1)
为此,您可能会通过使用消息队列异步执行此操作。这样,压缩就会添加到队列中,您可以让一台服务器执行此操作,也可以使用多台服务器。我不知道这是否符合您的要求。
我之前使用过Rabbit MQ(http://www.rabbitmq.com/)。