从动作返回文件时,流会被释放吗? [复制]

Posted

技术标签:

【中文标题】从动作返回文件时,流会被释放吗? [复制]【英文标题】:Does a Stream get Disposed when returning a File from an Action? [duplicate] 【发布时间】:2017-07-03 11:47:00 【问题描述】:

我正在向MemoryStream 写入一个字符串,我需要将流返回到控制器操作,以便我可以将其作为文件发送出去以供下载。

通常,我将 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;

返回文件的控制器动作:

[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?

【问题讨论】:

好问题。除非有明确的文档这么说(还没有真正看过),否则您可以实现自己的自定义流并检查其 dispose 方法是否被调用过。 【参考方案1】:

这里根据源代码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();
        
    

【讨论】:

以上是关于从动作返回文件时,流会被释放吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat服务器关闭时,如果在线程中使用JDBC数据库连接,它们会被释放吗?

linux 用户进程结束后 malloc申请的内存会自动释放吗,进程退出后malloc的内存是否会被释放?

方法返回的对象会被放入自动释放池吗?

返回通过 objectAtIndex 从 NSMutableArray 检索到的对象 - 需要自动释放吗?

释放 LongPressGesture SwiftUI 时触发动作

在 atexit() 中释放