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 encodingautomaticallyを送信します。確かに、これにはオーバーヘッドが少しあり、ウェブブラウザには未知のダウンロード進捗状況が残っていますが、サーバーのメモリに最初に全体の応答をバッファする必要がないため、適切な最終応答コンテンツの長さを得ることができます。

あなた本当には、最終的な応答内容の長さを計算したい場合は、代わりにByteArrayOutputStreamにすべてを書いて、そのtoByteArray()方法でbyte[]を取得する必要があると思います。実際の応答内容の長さは、byte[]の長さです。

これは、すべてがサーバーのメモリに最初に格納されるため、これはメモリの混雑が増えるだけです。複数のユーザーが同時にこれを行い、zip出力が比較的大きい場合は、サーバーのメモリが不足する可能性があります。別の方法として、File#createTempFile()によって作成された一時ファイルにFileOutputStreamを書き込むことができます。その結果、File#length()でサイズを取得し、FileInputStreamを使用して通常の方法で応答のOutputStreamに直接ストリームします。基本的にバイトを2回転送するので、これは遅くなります。

+0

私はダウンロードファイルへの応答を書く疑いがあります。ダウンロード完了後にページをリダイレクトする方法は? – Palaniraja

+0

@Palaniraja:右上の「Ask Question」ボタンを押すだけで答えが得られます。 – BalusC

関連する問題