如何在 ASP.NET MVC 3 中从下载的文件优化内存中 zip 存档创建
本文关键字:优化 文件 内存 zip 创建 ASP NET MVC 下载 | 更新日期: 2023-09-27 18:36:30
我正在制作一个控制器,它应该返回从另一台服务器(位于同一数据中心)下载的文件的压缩列表
我为妈妈做了什么:
/// <summary>
/// Enables processing of the result of an action method by a custom type that inherits from the <see cref="T:System.Web.Mvc.ActionResult"/> class.
/// </summary>
/// <param name="context">The context in which the result is executed. The context information includes the controller, HTTP content, request context, and route data.</param>
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = "application/zip";
context.HttpContext.Response.CacheControl = "private";
context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.HttpContext.Response.AddHeader("content-disposition", string.Format("attachment; filename='"{0}'"", this.ResultFileName));
var buffer = new byte[BufferSize];
using (var zippedUploadStream = new ZipOutputStream(context.HttpContext.Response.OutputStream))
{
zippedUploadStream.SetLevel(0);
foreach (var url in this.Urls)
{
var request = WebRequest.Create(url);
var response = request.GetResponse();
var downloadStream = response.GetResponseStream();
if (downloadStream != null)
{
var zipEntry = new ZipEntry(Path.GetFileName(response.ResponseUri.ToString()));
zippedUploadStream.PutNextEntry(zipEntry);
int read;
while ((read = downloadStream.Read(buffer, 0, buffer.Length)) > 0)
{
zippedUploadStream.Write(buffer, 0, read);
context.HttpContext.Response.Flush();
}
}
if (!context.HttpContext.Response.IsClientConnected)
{
break;
}
}
zippedUploadStream.Finish();
}
context.HttpContext.Response.Flush();
context.HttpContext.Response.End();
}
让我害怕的是,所有操作都是同步的。
如果我离开这个实现,性能会受到多大的打击?
是否可以访问上下文。来自另一个线程的 HttpContext.Response 对象?
是否可以使用异步调用优化此代码?
您真的不希望从 Web 请求线程中执行这样的任务。这些类型的长时间运行、系统资源密集型任务最好使用某种队列或消息总线系统来执行。我推荐像NServiceBus这样的东西来完成这个任务。您不必从单个 Web 请求线程中同步创建多个 Web 请求,而是使用 NServiceBus 将消息排队。然后,NServiceBus 将选取其中每条消息(可能是异步的,具体取决于配置)并单独处理它们。这样做的好处是,您可以获得 MSMQ 的可靠性和持久性优势,NServiceBus 将其用作其消息队列。