Как я могу удалить свой поток при реализации загрузки файла в ASP.NET?

У меня есть класс DocumentGenerator, который обертывает MemoryStream. Поэтому я реализовал IDisposable в классе.

Я не вижу, как/где я могу распоряжаться им, хотя.

Это мой текущий код, который выполняет загрузку файла в MVC:

using (DocumentGenerator dg = DocumentGenerator.OpenTemplate(path))
{
    /* some document manipulation with the 
       DocumentGenerator goes here ...*/

    return File(dg.GetDocumentStream(), "text/plain", filename);
}

Эти ошибки, когда поток закрыт/установлен до того, как контроллер завершит работу с ним. Как я могу убедиться, что мои ресурсы правильно настроены в этой ситуации?

EDIT: Моя реализация IDisposable на данный момент просто предоставляет MemoryStream. Я знаю, что это не правильная реализация, я просто использовал ее в качестве теста. Есть ли что-то другое, что я могу сделать здесь, чтобы заставить его работать?

public void Dispose()
{
    _ms.Dispose();
    _ms = null;
}

Ответ 1

Вам не нужно удалять поток. Он будет удален методом FileStreamResult.WriteFile. Выдержка кода из этого класса:

public FileStreamResult(Stream fileStream, string contentType) : base(contentType)
{
    if (fileStream == null)
    {
        throw new ArgumentNullException("fileStream");
    }
    this.FileStream = fileStream;
}

protected override void WriteFile(HttpResponseBase response)
{
    Stream outputStream = response.OutputStream;
    using (this.FileStream)
    {
        byte[] buffer = new byte[0x1000];
        while (true)
        {
            int count = this.FileStream.Read(buffer, 0, 0x1000);
            if (count == 0)
            {
                return;
            }
            outputStream.Write(buffer, 0, count);
        }
    }
}

Обратите внимание на using. Когда вы вызываете File(dg.GetDocumentStream(), "text/plain", filename) с вашего контроллера, он вызывает конструктор, который сохраняет поток в общедоступное свойство, которое расположено во время рендеринга.

Заключение: вам не нужно беспокоиться о том, чтобы избавиться от потока с помощью dg.GetDocumentStream().

Ответ 2

Чтобы добавить к тому, что сказал Дарин, важно отметить эту концепцию:

public Stream GetDownloadFile(...)
{
  using (var stream = new MemoryStream()) {
    return stream;
  }
}

public Stream GetDownloadFile(...)
{
  using (var generator = DocumentGenerator.OpenTemplate(path))
  {
    // Document manipulation.

    return File(generator.GetDocumentStream(), "text/plain", filename);
  }
}

Независимо от того, как вы используете его в своем методе, блок использования гарантирует, что Dispose всегда вызывается, это важно, если вы считаете, что использовать результат использования блока как оператора возврата, он не остановит его будучи расположенным....