2013-08-08 21 views
3

FILESTREAM을 지원하는 SQL 데이터베이스를 설치했으며 WebAPI를 통해 SqlFileStream을 사용하여 데이터베이스에서 검색 한 파일을 브라우저로 스트리밍하려고합니다.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을 스트리밍하는 적절한 방법은 무엇입니까?

답변

0

콘텐츠를 StreamContent으로 설정하는 대신 컨트롤러에서 fileStream을 읽고 byte 배열에 넣은 다음 ByteArrayContent? 내가 사용한 ReadFully 구현, here is a link to a Jon Skeet method를 들어

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); 

.

그리고 연결이 너무 일찍 종료되었다고 생각됩니다. 당신은 당신의 DbContext/ObjectContextusing 블럭에 멋지게 감싸고 있습니다. 그러나 나는 그것이 문제라고 생각합니다. 제어기가 HttpResponseMessage을 반환 한 후에 해당 컨텍스트가 삭제되지만 응답은 스트림에 대한 액세스 만 가지고 있습니다. 스트림을 읽고 브라우저 또는 클라이언트로 다시 전달하기 전에 여전히 스트림을 읽고 byte[]으로 변환해야합니다. 프레임이 여전히 내용을 읽기 위해 스트림에 액세스 할 수 있기 때문에 보통 MemoryStream 등을 사용할 때 자동으로 발생합니다. 이 경우 스트림을 읽기 전에 SQL 연결을 삭제합니다.

또 다른 해결책은 작업 방법에 newing 그것을 대신 DbContext에 대한 의존성 주입을 사용할 수 있습니다. HTTP 요청의 끝에서 컨텍스트를 자동으로 처리하도록 IoC 컨테이너를 설정하면 프레임 워크가 StreamContentbyte[]으로 변환하고 네트워크를 통해 다시 푸시 할 때 사용할 수 있어야합니다.

+1

작동하는 동안 그것을 바이트 []로 읽는 것은 유혹적인 선택이 아닙니다. 그렇게하면 스트리밍의 이점을 완전히 잃어 버리며 대용량 파일을 처리 할 때 큰 문제가 발생합니다. – magnattic

+0

TransactionScope 대신 CommitableTransaction을 사용하고 Controllers dispose 메서드에서 처리를 늦게 처리하여 문제를 해결했습니다. ("사용"블록을 사용하는 대신) 의존성 주입 솔루션에 대해 자세히 설명해 주시겠습니까? 그게 정확히 어떻게 작동할까요? 예를 들어 줄 수 있습니까? – magnattic

+0

웹상에서 MVC 및 WebAPI 컨트롤러 생성자 주입을 사용하여 'DbContext'에 대한 제어 수명 범위의 종속성 주입/반전의 예가 많이 있습니다. 당신이 내 도움을 필요로해서는 안됩니다. – danludwig