Не удается получить доступ к 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();
Я подхожу ближе и избавляюсь от них всех.