这是一个非常简单的示例,如何将Stream
返回给 ASP.NET MVC:
public ActionResult DownloadData(...)
{
using(var lib = new SomeLibrary())
{
// do some stuff...
var stream = new MemoryStream();
lib.SaveAs(stream);
stream.Position = 0;
return File(stream, "contenttype", "filename");
}
}
问题是MemoryStream
将被分配到大的堆对象区域,并且在 32 位系统上,它很快就会导致OutOfMemoryException
,因为 RAM 碎片会阻止分配大内存块,即使有足够的内存。在 64 位系统上,此方法也非常慢。
我想要的只是返回一个流,类似于这个
public ActionResult DownloadData(...)
{
using(var lib = new SomeLibrary())
{
// do some stuff...
return File(lib.Stream, "contenttype", "filename");
}
}
但是,在返回数据之前,using
语句将调用.Dispose()
。如果我完全删除 using
语句,则库将锁定资源,直到垃圾回收器清理内存。
我认为最好的解决方案是使用通用Stream
,它只是复制源流并在最后调用.Dispose()
:
public ActionResult DownloadData(...)
{
var lib = new SomeLibrary()
try
{
// do some stuff...
var stream = new CopyStream(lib.Stream, lib);
return File(stream, "contenttype", "filename");
}
catch(Exception)
{
lib.Dispose();
throw;
}
}
通用流应在关闭后lib
调用第二个参数的.Dispose()
。
在 .NET 或 NuGet 中是否有此类Stream
的现有实现?
也许我不完全了解您需要什么,但在您的情况下,无需自己处理流(使用显式 Dispose(( 调用或使用 using 关键字(。
来自ASP MVC控制器的文件帮助程序方法旨在返回流:它创建一个FileStreamResult,负责处理封装的流,并在完成其工作时执行此操作。
关于这个话题,你可以在这里找到达林·季米特洛夫更好、更详细的答案。