【发布时间】:2017-08-14 12:56:04
【问题描述】:
我正在尝试将存储在 sql server 中的内容作为 varbinary(max) 流式传输到客户端。我能够使它工作,但是连接将保持打开状态,直到垃圾收集。如果我在返回结果之前处置连接、阅读器或蒸汽,则会导致对象处置错误。
我希望避免将数据复制到内存中(因为它可能很大),同时在完成后正确处理对象。实现这两个目标的最佳方式是什么。
如果相关,我正在使用 .NET Core 2.0。
更新:这不是与其他人 (How do I dispose my filestream when implementing a file download in ASP.NET?) 的重复,因为我不是在问如何处理流,而是在问如何处理相关的连接对象。我的问题更多是关于确保连接对象被释放的正确方法
下面的代码成功返回结果,但留下一个未释放的连接:
public async Task<IActionResult> DownloadFile(Guid FileId)
{
var connection = new SqlConnection(DatabaseService.ConnectionString);
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "select FileName, FileContent from Files where FileId=@FileId";
command.CommandType = System.Data.CommandType.Text;
command.Parameters.AddWithValue("@FileId", FileId);
var reader = await command.ExecuteReaderAsync(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleRow);
if (!await reader.ReadAsync())
return NotFound();
var attachmentName = Convert.ToString(reader[0]);
var stream = reader.GetStream(1);
var response = File(stream, "application/octet-stream", attachmentName);
return response;
}
下面的这段代码处理了对象,但由于首先被处理而无法流式传输内容
public async Task<IActionResult> DownloadFile(Guid FileId)
{
using (var connection = new SqlConnection(DatabaseService.ConnectionString))
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandText = "select FileName, FileContent from Files where FileId=@FileId";
command.CommandType = System.Data.CommandType.Text;
command.Parameters.AddWithValue("@FileId", FileId);
using (var reader = await command.ExecuteReaderAsync(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleRow))
{
if (!await reader.ReadAsync())
return NotFound();
var attachmentName = Convert.ToString(reader[0]);
using (var stream = reader.GetStream(1))
{
var response = File(stream, "application/octet-stream", attachmentName);
return response;
}
}
}
}
}
【问题讨论】:
-
这不是与其他人的重复,因为我不是在问如何处理流,而是在问如何处理相关的连接对象。我的问题更多是关于确保连接对象被释放的正确方法
-
@musefan 不幸的是,您的新示例 (stackoverflow.com/questions/37956254/…) 没有解决流式传输的需求,并且接受的答案在发送响应之前将整个内容加载到内存流中。
-
您没有任何可靠的选择。连接是有限的/宝贵的,您需要尽快处理它们。读取所有数据然后关闭连接并发送数据是迄今为止最好的方法。还有其他方法,例如注册和处理对象,但您只是让连接保持打开状态,这样做没有优势。
-
Erik,看起来
HttpContext.Response.RegisterForDispose()有效,所以我可以流式传输结果,而不必担心完成后连接仍然存在
标签: c# .net sql-server asp.net-mvc asp.net-core