从操作返回文件时,流是否会被处置?
Does a Stream get Disposed when returning a File from an Action?
我正在将字符串写入 MemoryStream
我需要将流 return 发送到控制器操作,以便我可以将其作为文件发送以供下载。
通常,我将 Stream 包装在 using 语句中,但在这种情况下,我需要 return 它。在我 return 之后它仍然会被处置吗?还是我需要自己以某种方式处理它?
//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;
}
return文件的控制器操作:
[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?
}
根据这里的源代码aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/FileStreamResult.cs
是
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);
}
}
}
其中 FileStream
是您调用
时传递的流
return File(stream, "application/octet-stream", "forums.csv");
更新。
您的问题最初被标记为 Asp.Net MVC,但代码看起来像是更新的核心框架。
在那里也找到了它,虽然写法不同,但它在技术上做同样的事情。
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();
}
}
}
我正在将字符串写入 MemoryStream
我需要将流 return 发送到控制器操作,以便我可以将其作为文件发送以供下载。
通常,我将 Stream 包装在 using 语句中,但在这种情况下,我需要 return 它。在我 return 之后它仍然会被处置吗?还是我需要自己以某种方式处理它?
//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;
}
return文件的控制器操作:
[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?
}
根据这里的源代码aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/FileStreamResult.cs
是
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);
}
}
}
其中 FileStream
是您调用
return File(stream, "application/octet-stream", "forums.csv");
更新。
您的问题最初被标记为 Asp.Net MVC,但代码看起来像是更新的核心框架。
在那里也找到了它,虽然写法不同,但它在技术上做同样的事情。
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();
}
}
}