Pergunta

Estou tendo um problema ao tentar servir um arquivo zip em um JSP.

O arquivo zip é sempre corrupto após ele tem download acabado. Eu tentei alguns métodos diferentes para leitura e escrita, e nenhum deles parece fazer o truque.

Eu acho que ele provavelmente está adicionando em caracteres ASCII em algum lugar como o arquivo será aberto e exibirá todos os nomes de arquivos, mas não posso extrair os arquivos.

Aqui está o meu código mais recente:

<%@ 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();
    }
%>

EDIT: Mudei o código para um servlet e ainda não funcionou. Eu mudei um monte mais coisas ao redor, então aqui está a última versão do código não-trabalho:

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 é o código servlet que realmente funciona. Obrigado 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();
    }
}
Foi útil?

Solução

Zips são arquivos binários e, portanto, não é adequado para ser transferido como dados de caracteres. Também texto fora do código pode corromper o arquivo.

Use, um servlet simples baunilha em vez do JSP.

Outras dicas

O JSP acrescenta espaços em branco para a saída. Eu sugiro que você se move a um servlet.

Como alternativa, você pode dar uma olhada em Retira espaço jsp saída, mas Eu não tenho certeza de que não iria afectar a própria saída ZIP.

O problema neste trecho exata é na linha dois - você tem uma linha em branco fora tags JSP, que é enviado para o navegador como HTML (ou seja, uma linha em branco em HTML).

Tenha muito cuidado para remover qualquer coisa que não está em <%%>, especialmente em branco (mesmo uma nova linha de terminais!), Ou seguir o conselho em outro lugar e usar um servlet:)

Seu código servlet não funciona porque você está a saída de seu fluxo para response.getWriter(), que, como outros têm para fora pontas é para dados caracteres . Cito o Javadoc:

PrintWriter getWriter() throws IOException
Retorna um objeto PrintWriter que podem enviar mensagens de texto de caracteres para o cliente. O PrintWriter usa a codificação de caracteres retornado por getCharacterEncoding ()

Não só isso, mas você não está mesmo escrevendo a matriz de bytes para o Writer, você está escrevendo os resultados de ByteArrayOutputStream.toString(), que também faz uma conversão de caráter ~

Você quer usar response.getOutputStream (), algo como:

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

E, em seguida, escrever o conteúdo de bytes de seu arquivo a ele.

Os leitores são tipicamente para fluxos de caracteres se bem me lembro - que você pode tentar algo mais ao longo das linhas de um ByteArrayOutputStream? Além disso, o JSP poderia realmente estar corrompendo a saída como outros têm comentado.

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

Além da questão Servlet / JSP, esta linha está corrompendo seus dados com 100% de certeza. Ele vai tentar interpretar os dados binários como texto usando a codificação padrão da plataforma, o que significa que cerca de metade dos bytes no arquivo são substituídos por "caráter desconhecido".

Bytes e cordas não são a mesma coisa!

Eu também sugeriria usar um servlet simples e consideraria resposta de Robert Munteanu como certo, mas você poderia fazer isso em seu JSP também. O problema não é o espaço em branco adicionado, mas que a variável implícito "out" é uma instância de JspWriter e um escritor é para os personagens, não para bytes. Tente usar response.getOutputStream () e direito sobre ele, que deve funcionar. Você receberá uma exceção dizendo que outra pessoa já tem o OutputStream, mas você pode ignorá-lo.

Mas como eu disse, usando um servlet seria muito mais limpo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top