从动作返回文件时,流是否会被处置?

Nee*_*ack 16 c# memorystream streamwriter asp.net-core-mvc asp.net-core

我正在写一个字符串,MemoryStream我需要将流返回到Controller Action,所以我可以将其作为文件发送下载.

通常,我将Stream包装在using语句中,但是,在这种情况下,我需要返回它.我退货后还能处理吗?或者我需要以某种方式自行处理它?

//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;
}
Run Code Online (Sandbox Code Playgroud)

Controller返回文件的Action:

[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?
}
Run Code Online (Sandbox Code Playgroud)

Nko*_*osi 18

根据源代码这里aspnetwebstack/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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

FileStream你打电话的时候会在哪里流过

return File(stream, "application/octet-stream", "forums.csv");
Run Code Online (Sandbox Code Playgroud)

更新.

您的问题最初被标记为Asp.Net MVC,但代码看起来像是最新的核心框架.

在那里找到它虽然写得不同但它在技术上做同样的事情.

ASPNET/MVC/BLOB的/ dev/src目录/ Microsoft.AspNetCore.Mvc.Core /基础设施/ FileStreamResultExecutor.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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)