2013-07-25 9 views
6

그래서 MVC 프로젝트가 있습니다. 이 MVC 프로젝트에는 컨텐트를 클라이언트로 다시 스트리밍해야하는 컨트롤러가 하나 있습니다. 스트리밍이 시작되면 콘텐츠 길이를 결정할 방법이 없습니다 (즉석에서 계산 됨). (이미 적절한 HTTP 헤더를 버퍼링 된 출력을 비활성화하고, 첨부했습니다) 그래서 나는 HttpContext.Current.Response.OutputStream 열고 주기적으로 작성 및 세척을 시작합니다청크 분할 콘텐츠 인코딩을 반환하는 MVC 컨트롤러

while (some condition){ 

    HttpContext.Current.Response.OutputStream.Write(buffer, 0, buffer.Length); 
    HttpContext.Current.Response.Flush(); 
} 

그때 닫 스트림을 강제하는 경우 :

HttpContext.Current.Response.Close(); 

이 제대로 (이것은 클라이언트에 EOF를 나타 내기 위해, 마지막에 0 길이 덩어리를 추가하지 않음) 청크 내용을 종료하지 않습니다.

내가 대신 더 정상적으로 출력 스트림을 닫으면 :

HttpContext.Current.Response.End(); 

또는

HttpContext.Current.ApplicationInstance.CompleteRequest(); 

제대로 스트림 (끝에 추가 제로 길이의 덩어리를) 종료를,하지만 난에 의해 throw 예외가 스트림이 이미 작성되었으므로 HTTP 헤더를 출력 스트림에 삽입 할 수 없다는 것을 나타내는 응용 프로그램입니다.

두 경우 모두 Controller는 null (또는 EmptyActionResult)을 반환합니다.

MVC 스택에서 Controller가 실행 완료 후 모든 ActionResult가 HTTP 헤더를 설정해야하므로 예외가 발생한 것으로 가정합니다. 이 경우 MVC에서 청크 분할 스트림을 어떻게 구현합니까?

미리 감사드립니다.

편집 : 정확한 예외가 발생되고있다 :

Uncaught Exception: System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent. 
    at System.Web.Http.WebHost.HttpControllerHandler.EndProcessRequest(IAsyncResult result) 
    at System.Web.Http.WebHost.HttpControllerHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) 
    at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
    at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) 

답변

2

나는 해결책을 찾아 냈다.

부호화는 0 길이 청크 닫아야 청크는 HTTP 1.1 표준 지정이 요청 모드 킵 얼라이브

상시 모드 인 경우에만, 클라이언트/서버 사이의 연결은 여러 동안 지속되고 요청/응답. 앞에서 설명한 응답이 끝나는 시점을 클라이언트가 알 수있는 다른 방법이 없기 때문에 청크 인코딩은이 컨텍스트에서 길이가 0 인 청크로 끝나야합니다.

"Connection : keep-alive"가 아니라 "Connection : close"를 헤더로 지정하면 요청이 연결간에 지속되지 않고 클라이언트가 응답 종료의 표시로 닫는 연결을 사용할 수 있습니다. EOF를 나타내는 0 길이 청크가 필요하지 않습니다.

난 그냥 수동으로 사용하여 HttpResponse에를 종료하기로 결정했습니다 : 이전 코드에 규정 한 것은 연결이 EOF에 종료됩니다 것을 클라이언트에게

HttpContext.Current.Response.Close(); 

동안. 이것은 클라이언트가 0 길이 청크를 수신하지 못하는 문제를 해결했습니다. 이제 클라이언트가이를 요구하지 않기 때문입니다.

관련 문제