代码之家  ›  专栏  ›  技术社区  ›  H. Pauwelyn

无法访问响应。ASP中的OutputStream。NET MVC应用程序,因为它已关闭

  •  2
  • H. Pauwelyn  · 技术社区  · 7 年前

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

    System.ObjectDisposedException : 无法访问封闭流。

    这是我的密码。我正在ASP中使用C#。NET MVC应用程序。

    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();
        }
    }
    

    这个代码怎么了?

    1 回复  |  直到 7 年前
        1
  •  1
  •   H. Pauwelyn    7 年前

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

    如果不处理 MemoryStream 不要打电话接近它。可能是在调用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();
        }
    }
    

    为了确保所有流都已关闭,我添加了所有打开的 内存流 s到列表和之前 Response.End(); ,我走近去把它们都处理掉。

    推荐文章