通过WebAPI流SqlFileStream

时间:2013-08-08 14:56:34

标签: asp.net sql-server asp.net-web-api sqlfilestream

我已经设置了一个支持FILESTREAM的SQL数据库,并尝试使用SqlFileStream通过WebAPI将从数据库中检索到的文件流式传输到浏览器。

由于某种原因,它不起作用,但我没有得到正确的错误消息。浏览器只是中止连接,Fiddler也没有显示任何有用的东西,并且VS中似乎没有出现任何错误。

public HttpResponseMessage Get(Guid id)
{
    if(id == null || id == Guid.Empty)
        return Request.CreateResponse(HttpStatusCode.BadRequest);

    try
    {
        FileStreamContext fsc = null;
        Document document = null;
        using(var transaction = new TransactionScope())
        using (var db = new MyEntities())
        {
            try
            {
                fsc = db.Database.SqlQuery<FileStreamContext>("SELECT [File].PathName() AS InternalPath, GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext FROM Document WHERE id={0}", id).First();
            }
            catch (Exception e)
            {
                Debug.Print(e.ToString());
            }

            document = db.Documents.Where(doc => doc.ID == id).Single();

            var fileStream = new SqlFileStream(fsc.InternalPath, fsc.TransactionContext, FileAccess.Read);

            HttpResponseMessage response = new HttpResponseMessage();
            response.Content = new StreamContent(fileStream);
            //response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            //response.Content.Headers.ContentDisposition.FileName = document.FileName;
            response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(document.ContentType);
            return response;
        }
    }
    catch (Exception e)
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}

我怀疑TransactionScope提前关闭可能会出现问题?不知道为什么我没有收到任何错误消息。

通过WebApi流式传输SqlFileStream的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

您是否尝试阅读控制器中的StreamContent,将其放入fileStream数组,然后使用{{{}设置内容,而不是将内容设置为byte。 1}}?

ByteArrayContent

对于我已使用的var fileStream = new SqlFileStream(fsc.InternalPath, fsc.TransactionContext, FileAccess.Read); byte[] fileContent = fileStream.ReadFully(); // you will need to implement ReadFully HttpResponseMessage response = new HttpResponseMessage(); response.Content = new ByteArrayContent(fileContent); 实施,here is a link to a Jon Skeet method

我怀疑你过早关闭连接是正确的。您已将ReadFully / DbContext很好地包裹在ObjectContext块中,但我认为这是问题所在。在控制器返回using之后,该上下文正在处理,但响应只能访问流 - 它仍然需要读取流并将其转换为HttpResponseMessage,然后再返回浏览器或客户。当您使用byte[]等时,这通常会自动发生,因为框架仍然可以访问流来读取其内容。但在这种情况下,您可以在读取流之前处置SQL连接。

另一个解决方案可能是为MemoryStream使用依赖注入,而不是在action方法中新建它。如果您将IoC容器设置为在HTTP请求结束时自动处理上下文,那么当框架将DbContext转换为StreamContent时,它仍应可用(不存在)把它推回网络。