无法访问 ASP.NET MVC 应用程序中的 Response.OutputStream,因为它已关闭
Posted
技术标签:
【中文标题】无法访问 ASP.NET MVC 应用程序中的 Response.OutputStream,因为它已关闭【英文标题】:Cannot access Response.OutputStream in an ASP.NET MVC application because it's closed 【发布时间】:2018-09-05 10:51:21 【问题描述】:我正在尝试在我的 Web 应用程序中从另一个域传输文件,我将压缩此文件以供下载。为此,我使用 Ionic Zip。但是我的代码中的标记行出现了这个错误:
System.ObjectDisposedException
: 无法访问已关闭的 Stream。
这是我的代码。我在 ASP.NET MVC 应用程序中使用 C#。
using Ionic.Zip;
using System.IO;
using System.Net;
[HttpPost]
public async Task<ActionResult> Downloads(string lang, string product, IEnumerable<string> file, string action)
string zipname = "manuals.zip";
using (ZipFile zip = new ZipFile())
foreach (string f in file.Distinct())
using (WebClient client = new WebClient())
using (MemoryStream output = new MemoryStream())
byte[] b = client.DownloadData(f);
await output.WriteAsync(b, 0, b.Length);
await output.FlushAsync();
output.Position = 0;
zip.AddEntry(f.Split('/').Last(), output);
output.Close();
Response.Clear();
Response.ContentType = "application/zip, application/octet-stream";
Response.AddHeader("content-disposition", $"attachment; filename=product.Replace('/', '-')-zipname");
zip.Save(Response.OutputStream); // ← error on this line
Response.End();
这段代码有什么问题?
【问题讨论】:
你能测试一下如果你不释放内存流并且不调用 close 会发生什么。可能会延迟读取实际内存流,直到调用Save
。在您的代码中,所有这些流都已经关闭、处置,甚至可能被 GC。
@rene:这行得通。但是所有的流会在Response.End()
之后关闭还是我必须手动关闭?
调用者通常负责关闭/处理它创建的内容。它可能会转移这种责任,但它必须明确地这样做。这些都不适用于 HttpResponse 的能力,所以是的,您需要手动完成。
【参考方案1】:
通过@rene 的评论,我找到了一个可行的答案。他说:
如果您不处置
MemoryStream
并且不调用 close 它,您能测试一下会发生什么。可能会延迟读取实际内存流,直到调用 Save 为止。在您的代码中,所有这些流都已经关闭、处置,甚至可能被 GC。
在这里查看我的代码。
using Ionic.Zip;
using System.IO;
using System.Net;
[HttpPost]
public ActionResult Downloads(string lang, string product, IEnumerable<string> file, string action)
string zipname = "manuals.zip";
List<MemoryStream> streams = new List<MemoryStream>();
using (ZipFile zip = new ZipFile())
foreach (string f in file.Distinct())
using (WebClient client = new WebClient())
MemoryStream output = new MemoryStream();
byte[] b = client.DownloadData(f);
output.Write(b, 0, b.Length);
output.Flush();
output.Position = 0;
zip.AddEntry(f.Split('/').Last(), output);
// output.Close(); // ← removed this line
streams.Add(output);
Response.Clear();
Response.ContentType = "application/zip, application/octet-stream";
Response.AddHeader("content-disposition", $"attachment; filename=product.Replace('/', '-')-zipname");
zip.Save(Response.OutputStream);
foreach (MemoryStream stream in streams)
stream.Close();
stream.Dispose();
Response.End();
为了确保所有流都已关闭,我已将所有打开的 MemoryStream
s 添加到列表中,在 Response.End();
之前,我关闭并将它们全部处理掉。
【讨论】:
以上是关于无法访问 ASP.NET MVC 应用程序中的 Response.OutputStream,因为它已关闭的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core mvc 应用程序中的 FFMPEG 录制
无法从 Asp.Net Mvc 应用程序中找到 DataContractJsonSerializer
如何在 ASP.NET MVC 5 中访问 AspNetUserRoles 表