在浏览互联网数小时后,我仍然摸不着头脑,不知道如何解决我的ASP.NET Core 2.x问题。
我正在动态生成CSV文件(可能需要几分钟时间),然后尝试将其发送回客户端。很多客户端在我开始发送响应之前就已经超时了,因此我试图向他们流式传输文件(并立即返回200响应),并异步写入该流。在以前的ASP中,似乎可以使用PushStreamContent
实现这一点,但我不确定如何构建我的代码,以使CSV生成过程是异步完成并立即返回HTTP响应。
[HttpGet("csv")]
public async Task<FileStreamResult> GetCSV(long id)
{
// this stage can take 2+ mins, which obviously blocks the response
var data = await GetData(id);
var records = _csvGenerator.GenerateRecords(data);
// using the CsvHelper Nuget package
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
var csv = new CsvWriter(writer);
csv.WriteRecords(stream, records);
await writer.FlushAsync();
return new FileStreamResult(stream, new MediaTypeHeaderValue("text/csv))
{
FileDownloadName = "results.csv"
};
}
如果你请求这个控制器方法,除非整个CSV生成完毕并且最终得到响应,否则你将什么都得不到。此时,大多数客户端请求已经超时。
我尝试过使用
Task.Run()
来包装CSV生成代码,但这并没有解决我的问题。
Response.Body
,例如new StreamWriter(Response.Body)
。但这并不能使缓慢的查询变快,您仍然会遇到超时问题。GetData
是做什么的?为什么需要 2 分钟?修复错误的查询可能比后台生成 CSV 文件更有效(也更快)。 - Panagiotis KanavosExecuteResultAsync
调用中执行整个读取-转换-流操作。如果您检查FileStreamResult的实现,您会发现您可以在该方法中自行完成任务,或者调用一个DI注册处理程序来完成它。 - Panagiotis Kanavos