2012-01-10 7 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() ralentiza reeeeally descargas abajo.
Si no lo uso o lo puse después de out.close() todo funciona bien, pero las descargas son mucho más rápidas.
¿Alguien me puede explicar por qué y si es necesario usar response.setContentLength()?Servlet: response.setContentLength() ralentiza descargar abajo

+0

Tu pregunta resolvió un problema que estaba teniendo con servlet-api-3.1 en Jetty 9. Eliminé el response.setContetLength() en mi servlet; el tiempo de respuesta ahora coincide con lo que obtenía con las versiones anteriores de Jetty. – faizal

+0

@faizal Me alegro de haber sido de ayuda. – Simon

Respuesta

20

Tal vez porque especifica un tamaño mayor que el que realmente se envió a la respuesta y el navegador web básicamente se confunde y está esperando más información. Ya sabes, ZIP comprime los archivos y reduce el tamaño final.

Simplemente no especifique la duración del contenido de la respuesta si no puede calcularla de antemano de manera eficiente. El contenedor de servlets lo enviará automatically de todas formas con chunked encoding. Es cierto que esto tiene un poco más de sobrecarga y deja el navegador web con un progreso de descarga desconocido, pero esto no requiere que almacene el buffer de toda la respuesta en la memoria del servidor primero para que pueda obtener la duración adecuada del contenido de la respuesta final.

Si realmente desea calcular la longitud del contenido respuesta final, que había necesidad de escribirlo todo a un lugar ByteArrayOutputStream y luego obtener el byte[] por su método toByteArray(). La longitud del contenido de la respuesta real es entonces la longitud del byte[].

Esto es solo más memoria porque todo se almacenará primero en la memoria del servidor. Si varios usuarios hacen esto al mismo tiempo y la salida zip es relativamente grande, entonces su servidor podría correr el riesgo de quedarse sin memoria tarde o temprano. Como otra alternativa, puede escribirlo usando FileOutputStream en un archivo temporal creado por File#createTempFile(), de modo que puede obtener su tamaño por File#length() y usar FileInputStream para transmitirlo directamente al OutputStream de la respuesta de la manera habitual. Esto es solo más lento ya que básicamente transfieres los bytes dos veces.

+0

Tengo una duda para escribir una respuesta al archivo de descarga..¿Cómo redirigir la página después de la descarga completa? – Palaniraja

+0

@Palaniraja: solo presiona el botón "Preguntar" en la parte superior derecha para obtener una respuesta. – BalusC

Cuestiones relacionadas