Не удается получить доступ к Response.OutputStream в приложении ASP.NET MVC, потому что оно закрыто

Я пытаюсь передать файл в своем веб-приложении из другого домена, и я заархивирую эти файлы для загрузки. Для этого я использую Ionic Zip. Но у меня есть эта ошибка в отмеченной строке в моем коде:

System.ObjectDisposedException: Нет доступа к закрытому потоку.

Вот мой код Я использую C# в приложении ASP.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 ответ

Решение

По комментарию @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();
    }
}

Чтобы быть уверенным, что все потоки закрыты, я добавил все открытые MemoryStreamс списка и до Response.End();Я подхожу ближе и избавляюсь от них всех.

Другие вопросы по тегам