2

我正在尝试从另一个域在我的 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();
    }
}

这段代码有什么问题?

4

1 回答 1

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();,我关闭并将它们全部处理掉。

于 2018-03-27T07:10:46.587 回答