【问题标题】:Most efficient way to write large files to HttpResponse in ASP.NET在 ASP.NET 中将大文件写入 HttpResponse 的最有效方法
【发布时间】:2011-04-29 08:12:13
【问题描述】:

我正在动态创建一个 ZIP 文件。我正在使用dotnetzip 来执行此操作。 我的 ZIP 文件的大小可以达到 500 MB,许多用户都试图同时下载它。

提供文件的最有效方式是什么?如果可以选择,我也不希望将文件保存在磁盘上,因为可能会导致严重的磁盘空间限制。

编辑:更多关于我的用例:

我们将文件托管在 SharePoint 2010 资产库中,该资产库托管在拥有世界各地用户的 Intranet 站点中。这些文件的大小通常为 10-80 MB。用户希望能够一次下载多个文件。

【问题讨论】:

  • 你能告诉我们更多关于用例的信息吗?将网络用于这些大小的文件,而不会像设计缺陷那样缓存 - 但当然您的用例可能与更常见的不同。

标签: c# .net asp.net streaming


【解决方案1】:

嗯,理论上

对于传统的 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);

请参阅 Best way to copy between two Stream instances - C# 了解 CopyStream 的实现。

然而实际上

考虑一下,这意味着如果 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 并使用 zip.Save(OutputStream) 将其直接写入输出流,那么事情少了很多麻烦。我的建议是首先以简单的方式执行此操作,然后进行测试,看看您是否遇到了仅通过创建一次 zip 即可解决的性能问题。

【讨论】:

【解决方案2】:

为此,您最好使用消息队列异步执行此操作。这样,压缩被添加到队列中,您可以让一台服务器或多台服务器来执行此操作。我不知道这是否符合您的要求。

我以前用过 Rabbit MQ (http://www.rabbitmq.com/)。

【讨论】:

    猜你喜欢
    • 2011-06-06
    • 2012-08-06
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多