C# 如何在不缓冲的情况下将文件从数据库异步流式传输到webclient

C# 如何在不缓冲的情况下将文件从数据库异步流式传输到webclient,c#,asp.net-web-api,.net-4.5,C#,Asp.net Web Api,.net 4.5,我正在尝试使用.NET4.5和WebAPI将文件从SQLServer异步流式传输到web客户端 我使用SqlDataReader.GetStream()从数据库中获取流。但是,当webapi从流中读取完毕时,我不确定如何连接db连接的处理/关闭 有任何示例吗?您可以编写一个包装流,从底层流读取数据,直到耗尽为止,然后处理所有相关资源(如SqlConnection) 我不是WebAPI专家,所以可能有一种更优雅的方法。但这在任何情况下都适用于流的标准WebAPI支持。您可以在WebAPI中执行以下

我正在尝试使用.NET4.5和WebAPI将文件从SQLServer异步流式传输到web客户端

我使用SqlDataReader.GetStream()从数据库中获取流。但是,当webapi从流中读取完毕时,我不确定如何连接db连接的处理/关闭


有任何示例吗?

您可以编写一个包装流,从底层流读取数据,直到耗尽为止,然后处理所有相关资源(如SqlConnection)


我不是WebAPI专家,所以可能有一种更优雅的方法。但这在任何情况下都适用于流的标准WebAPI支持。

您可以在WebAPI中执行以下操作。这里我使用
PushStreamContent
连接到数据库并检索Sql流。然后,我将此sql流直接复制到响应流。在Web API中,当您使用PushStreamContent时,客户端将以分块传输编码接收响应,因为您没有设置响应的内容长度。如果这对您合适,您可以使用下面的示例。否则,我将尝试看看是否有其他更好的方法来实现这一点

注意:这是一个基于PushStreamContent和MSDN上有关从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
    }
}

我尝试了一些类似的方法,但得到了一个错误:异步模块或处理程序在异步操作仍挂起时完成。您使用的是哪个版本的Web API?具体地说,您使用的是哪个版本的
Microsoft.AspNet.WebApi.Core
nuget软件包?您的意思是我的操作没有返回任务?…不,这不是必需的,因为我正在PushStreamContent的异步函数中执行基于异步的内容…我对上面的代码做了一些修改,现在就尝试了,它工作正常…您可以吗分享您的实现,想知道是否有任何细微的差异导致了您所看到的问题?我只是无法让上述工作正常进行。我三次检查代码都没有用。尝试了另一个答案的建议,只要我设置了内容长度标题并将其标记为答案,就行了,因为我无法让推流内容工作。我创建了一个包装流并设置了内容长度以使其正常工作。如果没有内容长度,它将无法工作(在IIS和selfhost中使用owin)