Pregunta

Tengo un problema al intentar servir un archivo zip en un JSP.

El archivo zip siempre está dañado una vez que ha finalizado la descarga. He probado algunos métodos diferentes para leer y escribir, y ninguno de ellos parece funcionar.

Supongo que probablemente esté agregando caracteres ascii en alguna parte, ya que el archivo se abrirá y mostrará todos los nombres de archivo, pero no puedo extraer ningún archivo.

Aquí está mi último código:

<%@ page import= "java.io.*" %>

<% 
    BufferedReader bufferedReader = null;

    String zipLocation = "C:\\zipfile.zip"; 

    try
    {
        bufferedReader = new BufferedReader(new FileReader(zipLocation));
        response.setContentType("application/zip");
        response.setHeader( "Content-Disposition", "attachment; filename=zipfile.zip" );

        int anInt = 0;
        while((anInt = bufferedReader.read()) != -1)
        {
            out.write(anInt);
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
%>

EDITAR: Moví el código a un servlet y todavía no funcionó. Cambié un montón de cosas más, así que aquí está el último código que no funciona:

public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
{
    try
    {
        String templateLocation = Config.getInstance().getString("Site.templateDirectory");

        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=output.zip;");

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(baos);
        FileInputStream fis = new FileInputStream(templateLocation);

        int len;
        byte[] buf = new byte[1024];

        while ((len = fis.read(buf)) > 0)
        {
            bos.write(buf, 0, len);
        }

        bos.close();
        PrintWriter pr = response.getWriter();
        pr.write(baos.toString());
        pr.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

EDIT2:

Este es el código de servlet que realmente trabajo. ¡Gracias a todos!

public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
{
    try
    {
        String templateLocation = Config.getInstance().getString("Site.templateDirectory");

        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=output.zip;");

        BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
        FileInputStream fis = new FileInputStream(templateLocation);

        int len;
        byte[] buf = new byte[1024];

        while ((len = fis.read(buf)) > 0)
        {
            bos.write(buf, 0, len);
        }

        bos.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
¿Fue útil?

Solución

Las cremalleras son archivos binarios y, por lo tanto, no son adecuadas para ser transferidas como datos de caracteres. También el texto fuera del código puede dañar el archivo.

Use un servlet de vainilla en lugar del JSP.

Otros consejos

El JSP agrega espacios en blanco a la salida. Le sugiero que mueva esto a un servlet.

Alternativamente, puede echar un vistazo a Eliminar espacios en blanco de la salida jsp , pero No estoy seguro de que no afecte la salida ZIP en sí.

El problema en este fragmento exacto está en la línea dos: tiene una línea en blanco fuera de las etiquetas JSP, que se envía al navegador como HTML (es decir, una línea en blanco en la fuente HTML).

Tenga mucho cuidado de eliminar todo lo que no esté en <%% > ;, especialmente los espacios en blanco (¡incluso una nueva línea terminal!), o siga los consejos en otro lugar y use un servlet:)

Su código de servlet no funciona porque está enviando su flujo a response.getWriter(), que como otros han señalado es para datos de caracteres . Cito el Javadoc:

  

PrintWriter getWriter() throws IOException
  Devuelve un objeto PrintWriter que puede enviar texto de caracteres al cliente. PrintWriter utiliza la codificación de caracteres devuelta por getCharacterEncoding ()

No solo eso, sino que ni siquiera está escribiendo la matriz de bytes en Writer, está escribiendo los resultados de ByteArrayOutputStream.toString(), que también realiza una conversión de caracteres ~

Desea utilizar response.getOutputStream (), algo como:

BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());

Y luego escriba el contenido de bytes de su archivo.

Los lectores son típicamente para secuencias de caracteres si no recuerdo mal. ¿Podría intentar algo más en la línea de un ByteArrayOutputStream? Además, el JSP podría estar corrompiendo la salida como otros han comentado.

bufferedReader = new BufferedReader(new FileReader(zipLocation));

Además del problema de Servlet / JSP, esta línea está corrompiendo sus datos con 100% de certeza. Intentará interpretar los datos binarios como texto utilizando la codificación de plataforma predeterminada, lo que significa que aproximadamente la mitad de los bytes del archivo se reemplazan con & Quot; carácter desconocido & Quot ;.

¡Los bytes y las cadenas no son lo mismo!

También sugeriría usar un servlet simple y consideraría La respuesta de Robert Munteanu como correcta, pero también puede hacerlo en su JSP. El problema no es el espacio en blanco agregado, sino que la variable implícita & Quot; out & Quot; es una instancia de JSPWriter y un escritor es para caracteres, no para bytes. Intente utilizar response.getOutputStream () y justo en eso, debería funcionar. Obtendrá una excepción que dice que otra persona ya obtuvo OutputStream, pero puede ignorarlo.

Pero como dije, usar un Servlet sería mucho más limpio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top