How do I dispose my filestream when implementing a file download in ASP.NET?

fearofawhackplanet picture fearofawhackplanet · Jun 21, 2010 · Viewed 10.9k times · Source

I have a class DocumentGenerator which wraps a MemoryStream. So I have implemented IDisposable on the class.

I can't see how/where I can possibly dispose it though.

This is my current code, which performs a file download in MVC:

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

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

This errors as the stream is closed/disposed before the controller has finished with it. How can I make sure my resources are properly disposed in this situation?

EDIT: My implementation of IDisposable at the moment just disposes the MemoryStream. I know it's not a proper implementation, I just used it as a test. Is there something different I could do here to make it work?

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

Answer

Darin Dimitrov picture Darin Dimitrov · Jun 21, 2010

You don't need to dispose the stream. It will be disposed by the FileStreamResult.WriteFile method. Code excerpt from this class:

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

Notice the using. When you call File(dg.GetDocumentStream(), "text/plain", filename) from your controller this invokes the constructor which stores the stream into a public property which is disposed during the rendering.

Conclusion: you don't need to worry about disposing the stream obtain with dg.GetDocumentStream().