Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a Stream get Disposed when returning a File from an Action? [duplicate]

I'm writing a string to a MemoryStream I need to return the stream to the Controller Action so I can send it off as a file for download.

Normally, I wrap the Stream in a using statement, but, in this case, I need to return it. Does it still get Disposed after I return it? Or do I need to dispose it myself somehow?

//inside CsvOutputFormatter public Stream GetStream(object genericObject) {     var stream = new MemoryStream();     var writer = new StreamWriter(stream, Encoding.UTF8);     writer.Write(_stringWriter.ToString());     writer.Flush();     stream.Position = 0;     return stream; } 

Controller Action that returns the file:

[HttpGet] [Route("/Discussion/Export")] public IActionResult GetDataAsCsv() {     var forums = _discussionService.GetForums(_userHelper.UserId);      var csvFormatter = new CsvOutputFormatter(new CsvFormatterOptions());      var stream = csvFormatter.GetStream(forums);     return File(stream, "application/octet-stream", "forums.csv");      //is the stream Disposed here automatically? } 
like image 698
John-Luke Laue Avatar asked Feb 15 '17 00:02

John-Luke Laue


People also ask

Does FileStreamResult dispose stream?

Yes. It uses a using block around the stream, and that ensures that the resource will dispose.

How do I return a streamed file?

To return a file stream, you can use a FileStreamResult. This lets you specify the stream, the MIME type, and some other options (like the file name). // the stream when the transfer is complete.

What does stream close do?

Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. Instead of calling this method, ensure that the stream is properly disposed.


1 Answers

According to source code here aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/FileStreamResult.cs

Yes

protected override void WriteFile(HttpResponseBase response) {     // grab chunks of data and write to the output stream     Stream outputStream = response.OutputStream;     using (FileStream)     {         byte[] buffer = new byte[BufferSize];          while (true)         {             int bytesRead = FileStream.Read(buffer, 0, BufferSize);             if (bytesRead == 0)             {                 // no more data                 break;             }              outputStream.Write(buffer, 0, bytesRead);         }     } } 

Where FileStream would have been the stream passed when you called

return File(stream, "application/octet-stream", "forums.csv"); 

Update.

Your question was originally tagged as Asp.Net MVC but the code looks like the more recent core framework.

Found it there as well though written differently it does the same thing technically.

aspnet/AspNetCore/blob/master/src/Mvc/Mvc.Core/src/Infrastructure/FileResultExecutorBase.cs

protected static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue range, long rangeLength) {     var outputStream = context.Response.Body;     using (fileStream)     {         try         {             if (range == null)             {                 await StreamCopyOperation.CopyToAsync(fileStream, outputStream, count: null, bufferSize: BufferSize, cancel: context.RequestAborted);             }             else             {                 fileStream.Seek(range.From.Value, SeekOrigin.Begin);                 await StreamCopyOperation.CopyToAsync(fileStream, outputStream, rangeLength, BufferSize, context.RequestAborted);             }         }         catch (OperationCanceledException)         {             // Don't throw this exception, it's most likely caused by the client disconnecting.             // However, if it was cancelled for any other reason we need to prevent empty responses.             context.Abort();         }     } } 
like image 153
Nkosi Avatar answered Sep 29 '22 02:09

Nkosi