我已经设置了一个支持FILESTREAM的SQL数据库,并尝试通过WebAPI将从数据库中检索到的文件通过SqlFileStream流式传输到浏览器。
由于某些原因,它不工作,但我没有得到适当的错误信息。浏览器只是中止连接,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的正确方式是什么?
发布于 2013-08-10 01:22:05
不是将内容设置为StreamContent,而是尝试读取控制器中的fileStream,将其放入byte数组中,然后使用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);对于ReadFully实现,使用我使用的here is a link to a Jon Skeet method。
我怀疑你关于连接过早关闭的说法是对的。您将DbContext / ObjectContext很好地包装在一个using块中,但我认为这就是问题所在。该上下文在控制器返回HttpResponseMessage之后被处理,但是响应只有权访问流--在传递回浏览器或客户端之前,它仍然需要读取流并将其转换为byte[]。当您使用MemoryStream或类似工具时,这通常会自动发生,因为框架仍然可以访问流以读取其内容。不过,在这种情况下,您需要在读取流之前处理SQL连接。
另一种解决方案可能是对DbContext使用依赖注入,而不是在操作方法中更新它。如果您将IoC容器设置为自动处理HTTP请求末尾的上下文,那么当框架将StreamContent转换为byte[]并通过网络将其推送出去时,它应该仍然可用(未处理)。
https://stackoverflow.com/questions/18129311
复制相似问题