2009-06-25 4 views
55

우리가 작업하고있는 응용 프로그램의 경우 사용자가 웹 사이트를 통해 매우 큰 파일 (즉, 잠재적으로 많은 기가 바이트)을 업로드 할 수 있도록 허용해야합니다. 안타깝게도 ASP.NET MVC는 서비스를 시작하기 전에 전체 요청을 RAM에로드하는 것처럼 보입니다. 그런 응용 프로그램에는 이상적이지 않습니다. 특히, 다음과 같은 코드를 통해 문제를 회피하려고 :ASP.NET MVC로 대용량 파일 업로드 스트리밍

if (request.Method == "POST") 
{ 
    request.ContentLength = clientRequest.InputStream.Length; 
    var rgbBody = new byte[32768]; 

    using (var requestStream = request.GetRequestStream()) 
    { 
     int cbRead; 
     while ((cbRead = clientRequest.InputStream.Read(rgbBody, 0, rgbBody.Length)) > 0) 
     { 
      fileStream.Write(rgbBody, 0, cbRead); 
     } 
    } 
} 

버퍼 - 더 - 요청에-RAM 정신을 우회하는 데 실패합니다. 이 문제를 해결할 수있는 쉬운 방법이 있습니까?

+1

코드가 응용 프로그램에서 어디에 있습니까? 제어 장치? 매니저? 기준 치수? –

+0

나는이 질문이 오래되었다는 것을 알고있다. 그러나 내가 연구하고있는 프로젝트의 참고 자료로 사용하고있는 것은 정말 좋은 질문이다. 빠른 질문 - 변수 "cbRead"에 "cb"라고 표시해야하는 것은 무엇입니까? – KSwift87

+0

@ KSwift87'cb'은 안개 크릭에서 표준 앱 헝가리 표기법 인 "Count of Bytes"를 나타냅니다. –

답변

23

초기 코드는 기본적으로 정확합니다. 요구되는 유일한 변경 콘텐츠 길이를 결정하기 위해 전체 요청

request.ContentLength = clientRequest.ContentLength; 

전 스트림

request.ContentLength = clientRequest.InputStream.Length; 

변경 하였다; 후자는 단지 Content-Length 헤더를 확인하기 만하면 헤더가 가득 차게 전송되어야합니다. 이를 통해 IIS는 요청을 거의 즉시 스트리밍하기 시작할 수 있으므로 원래의 문제가 완전히 제거됩니다.

+1

에 포함되어 있습니다. 기본적으로 InputStream 속성을 만지면 디스크 버퍼링이 무의미 해집니다. 디스크 버퍼링 된 파일에 대한 스트림 핸들을 얻을 수 있습니까? –

+2

나는 결정할 수 없었지만, 일단 내가 일하는 것을 얻으면 심각하게 조사를 중단했다. –

14

물론이 작업을 수행 할 수 있습니다. RESTful file uploads with HttpWebRequest and IHttpHandler을 참조하십시오. 나는이 방법을 몇 년 동안 사용해 왔으며 최소한 수 기가 바이트의 파일로 테스트 된 사이트를 가지고있다. 본질적으로, 당신은 자신보다 더 쉬운 IHttpHandler를 만들고 싶습니다.

간단히 말해서 IHttpHandler 인터페이스를 구현하는 클래스를 만듭니다. 즉, IsReusable 속성과 ProcessRequest 메서드를 지원해야합니다. 그 외에도 web.config에는 사소한 변화가 있으며, 매력처럼 작동합니다. 요청 수명주기의이 단계에서 업로드되는 전체 파일이 메모리에로드되지 않으므로 메모리 문제를 해결할 수 있습니다. Web.config의에서,

<httpHandlers> 
<add verb="*" path="DocumentUploadService.upl" validate="false" type="TestUploadService.FileUploadHandler, TestUploadService"/> 
</httpHandlers> 

파일 참조

주, DocumentUploadService.upl, 실제로 존재하지 않습니다. 그것은 요청이 표준 핸들러에 의해 차단되지 않도록 대체 확장을 제공하기위한 것입니다. 파일 업로드 양식을 해당 경로로 지정하면 FileUploadHandler 클래스가 실행되어 실제로 파일을받습니다.

업데이트 : 사실, 내가 사용하는 코드는이 기사와 다르며, 나는 그것이 작동하는 이유를 발견하지 못했습니다. HttpPostedFile 클래스를 사용하는데, "파일이 MIME multipart/form-data 형식으로 업로드됩니다. 기본적으로 양식 필드와 업로드 된 파일을 포함하여 256KB보다 큰 모든 요청은 서버 메모리에 저장되는 것이 아니라 디스크에 버퍼링됩니다 . "

if (context.Request.Files.Count > 0) 
{ 
    string tempFile = context.Request.PhysicalApplicationPath; 
    for(int i = 0; i < context.Request.Files.Count; i++) 
    { 
     HttpPostedFile uploadFile = context.Request.Files[i]; 
     if (uploadFile.ContentLength > 0) 
     { 
      uploadFile.SaveAs(string.Format("{0}{1}{2}", 
       tempFile,"Upload\\", uploadFile.FileName)); 
     } 
    } 
} 
+0

코드가 내 것과 거의 같습니다. 유일한 차이점은 ASP.NET MVC에서 실행 중이며 새 IHttpHandler에서 직접 실행한다는 것입니다. 왜 차이가 있는지 아십니까? 거기에 내 코드에서 강제로 스트림을 끌어 와야합니까? –

+0

위 업데이트를 참조하십시오. – RedFilter

+0

업로드 진행 상황을 어떻게 표시합니까? –