我尝试使用.net 4.5和web api将文件从sql server异步流式传输到Web客户端。
我使用SqlDataReader.GetStream()从db获取流。但是,当webapi从流中读完时,我不确定如何处理数据库连接的处理/关闭。
那里有样品吗?
答案 0 :(得分:6)
您可以在Web API中执行以下操作。在这里,我使用PushStreamContent
连接到数据库并检索Sql流。然后我直接将此sql流复制到响应流。在Web API中,当您使用PushStreamContent时,客户端将以分块传输编码接收响应,因为您没有设置响应的内容长度。如果这对你没问题,你可以使用下面的例子。否则我会试着看看是否还有其他更好的方法来实现这一目标。
注意:这是一个基于PushStreamContent和MSDN上 this 关于从sql server检索二进制数据的文章的快速示例。
[RoutePrefix("api/values")]
public class ValuesController : ApiController
{
private const string connectionString = @"your connection string";
[Route("{id}")]
public HttpResponseMessage GetImage(int id)
{
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = new PushStreamContent(async (responseStream, content, context) =>
{
await CopyBinaryValueToResponseStream(responseStream, id);
});
return resp;
}
// Application retrieving a large BLOB from SQL Server in .NET 4.5 using the new asynchronous capability
private static async Task CopyBinaryValueToResponseStream(Stream responseStream, int imageId)
{
// PushStreamContent requires the responseStream to be closed
// for signaling it that you have finished writing the response.
using (responseStream)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand("SELECT [bindata] FROM [Streams] WHERE [id]=@id", connection))
{
command.Parameters.AddWithValue("id", imageId);
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
if (await reader.ReadAsync())
{
if (!(await reader.IsDBNullAsync(0)))
{
using (Stream data = reader.GetStream(0))
{
// Asynchronously copy the stream from the server to the response stream
await data.CopyToAsync(responseStream);
}
}
}
}
}
}
}// close response stream
}
}
答案 1 :(得分:1)
您可以编写一个从底层流中读取的包装流,直到它耗尽,然后处理所有相关资源(如SqlConnection)。
我不是WebAPI专家,所以可能有更优雅的方式来做。但是,无论如何,这都适用于流的标准WebAPI支持。