2012-01-10 3 views
13
private void downloadAllRelease(HttpServletRequest request, 
     HttpServletResponse response) { 
    LoginToken tok=getToken(request, response); 
    int size = 0; 
    try { 
     ArrayList<Release> releases = manager.getReleases(tok.getUsername); 
     ZipOutputStream out = new ZipOutputStream(response.getOutputStream()); 
     for (int i=0; i<releases.size(); i++) { 
      size += releases.get(i).getFile().length; 
      out.putNextEntry(new ZipEntry(releases.get(i).getFilename())); 
      out.write(releases.get(i).getFile()); 
      out.closeEntry(); 
     } 
     response.setContentLength(size); 
     response.setContentType("application/force-download"); 
     response.setHeader("Content-Disposition","attachment;filename=release.zip"); 
     out.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

response.setContentLength() 다운로드 속도가 느려집니다.
만약 내가 그것을 사용하지 않거나 out.close() 이후에 넣어도 모든 것이 잘 작동하지만 다운로드는 더 빠르다.
이유를 설명 할 수있는 사람이 있고 response.setContentLength()을 사용해야 할 필요가 있습니까?서블릿 : response.setContentLength() 다운로드 속도가 느려집니다.

+0

귀하의 질문은 제가 서티에서 servlet-api-3.1과 관련된 문제를 해결했습니다. 제 서블릿에서 response.setContetLength()를 제거했습니다. 응답 시간은 이전의 Jetty 버전에서 얻은 결과와 일치합니다. – faizal

+0

@faizal 도움이 된 것을 기쁘게 생각합니다. – Simon

답변

20

아마도 응답에 실제로 전송 된 것보다 큰 크기를 지정하고 있기 때문에 웹 브라우저가 기본적으로 혼란에 빠지며 더 많은 데이터를 기다리고 있습니까? ZIP은 파일을 압축하고 최종 크기를 줄입니다.

사전에 효율적으로 계산할 수없는 경우 응답의 콘텐츠 길이를 지정하지 마십시오. 어쨌든 서블릿 컨테이너는 chunked encoding과 함께 automatically으로 전송됩니다. 사실 이것은 오버 헤드가 조금 더 많아 웹 브라우저에 알 수없는 다운로드 진행 상태를 남겨 둡니다. 그러나 서버의 메모리에 전체 응답을 먼저 버퍼링 할 필요가 없으므로 최종 응답 내용의 길이가 적절하게 유지됩니다.

당신이 정말로 최종 응답 내용 길이를 계산할 경우, 대신 ByteArrayOutputStream에 모두를 작성하고 다음의 toByteArray() 방법으로 byte[]을 얻을 필요가 것입니다. 실제 응답 내용 길이는 byte[]의 길이입니다.

이것은 모든 것이 서버의 메모리에 먼저 저장되기 때문에 메모리가 더 많이 소모됩니다. 여러 사용자가 동시에이 작업을 수행하고 zip 출력이 비교적 큰 경우 서버가 조만간 메모리가 부족해질 위험이 있습니다. 또 다른 대안으로, 으로 생성 된 임시 파일에 FileOutputStream을 써서 쓸 수 있습니다. 따라서 File#length() 크기를 얻고 FileInputStream을 사용하여 응답의 OutputStream에 직접 스트리밍하면됩니다. 기본적으로 바이트를 두 번 전송하면 속도가 느려집니다.

+0

나는 파일 다운로드에 대한 응답을 쓰는 것에 의심의 여지가있다. 다운로드 완료 후 페이지를 리디렉션하는 방법은 무엇입니까? – Palaniraja

+0

@Palaniraja : 오른쪽 상단의 "질문하기"버튼을 눌러 대답을 얻으십시오. – BalusC

관련 문제