C# 无法访问ASP.NET MVC应用程序中的Response.OutputStream,因为它';关门了

C# 无法访问ASP.NET MVC应用程序中的Response.OutputStream,因为它';关门了,c#,asp.net-mvc,webclient-download,objectdisposedexception,ionic-zip,C#,Asp.net Mvc,Webclient Download,Objectdisposedexception,Ionic Zip,我正在尝试从另一个域在我的web应用程序中使用steam文件,我将压缩这些文件以供下载。为此,我使用离子拉链。但我在代码中的标记行上有一个错误: 系统。ObjectDisposedException:无法访问封闭流 这是我的密码。我正在ASP.NETMVC应用程序中使用C 使用Ionic.Zip; 使用System.IO; Net系统; [HttpPost] 公共异步任务下载(字符串语言、字符串产品、IEnumerable文件、字符串操作) { 字符串zipname=“manuals.zip”;

我正在尝试从另一个域在我的web应用程序中使用steam文件,我将压缩这些文件以供下载。为此,我使用离子拉链。但我在代码中的标记行上有一个错误:

系统。ObjectDisposedException
无法访问封闭流

这是我的密码。我正在ASP.NETMVC应用程序中使用C

使用Ionic.Zip;
使用System.IO;
Net系统;
[HttpPost]
公共异步任务下载(字符串语言、字符串产品、IEnumerable文件、字符串操作)
{
字符串zipname=“manuals.zip”;
使用(ZipFile zip=new ZipFile())
{
foreach(file.Distinct()中的字符串f)
{
使用(WebClient=newWebClient())
{
使用(MemoryStream输出=新的MemoryStream())
{
字节[]b=客户端下载数据(f);
wait output.WriteAsync(b,0,b.Length);
等待输出。FlushAsync();
输出位置=0;
AddEntry(f.Split('/').Last(),输出);
output.Close();
}
}
}
Response.Clear();
Response.ContentType=“应用程序/zip,应用程序/octet流”;
AddHeader(“content disposition”,$”附件;文件名={product.Replace('/','-')}-{zipname}”);
zip.Save(Response.OutputStream);//← 这行有错误
Response.End();
}
}

这个代码怎么了?

通过@rene的评论,我找到了一个有效的答案。他说,


如果不处理
MemoryStream
并且不调用close,您能测试一下会发生什么吗。可能是读取实际内存流被延迟,直到调用Save。在您的代码中,所有这些流都已经关闭、释放,甚至可能是GC'd

看这里我的代码

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();
    }
}
使用Ionic.Zip;
使用System.IO;
Net系统;
[HttpPost]
公共操作结果下载(字符串语言、字符串产品、IEnumerable文件、字符串操作)
{
字符串zipname=“manuals.zip”;
列表流=新列表();
使用(ZipFile zip=new ZipFile())
{
foreach(file.Distinct()中的字符串f)
{
使用(WebClient=newWebClient())
{
MemoryStream输出=新的MemoryStream();
字节[]b=客户端下载数据(f);
输出.写入(b,0,b.长度);
output.Flush();
输出位置=0;
AddEntry(f.Split('/').Last(),输出);
//output.Close();//← 删除此行
流。添加(输出);
}
}
Response.Clear();
Response.ContentType=“应用程序/zip,应用程序/octet流”;
AddHeader(“content disposition”,$”附件;文件名={product.Replace('/','-')}-{zipname}”);
Save(Response.OutputStream);
foreach(流中的MemoryStream流)
{
stream.Close();
stream.Dispose();
}
Response.End();
}
}

为了确保所有流都已关闭,我已将所有打开的
MemoryStream
s添加到一个列表中
Response.End()之前,我关闭并处理它们。

如果不处理memorystream并且不调用close,您能测试一下会发生什么吗。读取实际内存流可能会延迟到调用
Save
之后。在您的代码中,所有这些流都已经关闭、处理,甚至可能是GC'd。@rene:这是可行的。但是在
Response.End()
之后,所有流都会关闭吗?还是我必须手动关闭?调用方通常负责关闭/处理它创建的内容。它可能会转移这一责任,但它必须明确地这样做。所有这些都不适用于HttpResponse的功能,所以是的,您需要手动执行。