Как избавиться от файлового потока при загрузке файлов в ASP.NET? - PullRequest
21 голосов
/ 21 июня 2010

У меня есть класс 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);
}

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

РЕДАКТИРОВАТЬ: Моя реализация IDisposable на данный момент просто избавляется от MemoryStream. Я знаю, что это неправильная реализация, я просто использовал ее в качестве теста. Есть ли что-то другое, что я мог бы сделать здесь, чтобы это сработало?

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

Ответы [ 2 ]

32 голосов
/ 21 июня 2010

Вам не нужно утилизировать поток.Он будет удален методом 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().

0 голосов
/ 23 июня 2010

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

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

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

...