这就是我想出的。
标记:
<a class="btn btn-success" asp-page-handler="DownloadCsv">
Download CSV
</a>
处理程序:
public IActionResult OnGetDownloadCsv()
{
using MemoryStream memoryStream = new MemoryStream();
using CsvWriter writer = new CsvWriter(memoryStream);
// Write to memoryStream using SoftCircuits.CsvParser
writer.Flush(); // This is important!
FileContentResult result = new FileContentResult(memoryStream.GetBuffer(), "text/csv")
{
FileDownloadName = "Filename.csv""
};
return result;
}
此代码有效,但我希望它更有效地使用内存。照原样,它将整个文件内容写入内存,然后将该内存复制到结果中。因此,在将任何内容写入响应流之前,一个大文件将在内存中存在两次。我对 FileStreamResult 很好奇,但无法让它发挥作用。
如果有人可以对此进行改进,我很乐意将您的答案标记为已接受。
更新:
所以我意识到我可以修改上面的代码来使用FileStreamResult,方法是用这个替换最后一个块:
memoryStream.Seek(0, SeekOrigin.Begin);
FileStreamResult result = new FileStreamResult(memoryStream, "text/csv")
{
FileDownloadName = "Filename.csv"
};
return result;
除了调用memoryStream.GetBuffer() 来复制所有字节之外,它的工作原理几乎相同,它只是传递内存流对象。这是一个改进,因为我没有不必要地复制字节。
但是,缺点是我必须删除我的两个 using 语句,否则我会得到一个异常:
ObjectDisposedException:无法访问已关闭的 Stream。
看起来这是在额外复制字节或不清理我的流和 CSV 写入器之间进行权衡。
最后,我能够防止 CSV 写入器在处理流时关闭它,并且由于 MemoryStream 没有非托管资源,因此保持打开状态应该没有害处。