JSP, чтобы служить почтовому индексу, повреждает файл - PullRequest
0 голосов
/ 19 июня 2009

У меня возникла проблема при попытке отправить zip-файл в JSP.

ZIP-файл всегда поврежден после завершения загрузки. Я пробовал несколько разных способов чтения и записи, и ни один из них, похоже, не сработал.

Я полагаю, что это где-то добавление символов ascii, поскольку файл откроется и отобразит все имена файлов, но я не могу извлечь какие-либо файлы.

Вот мой последний код:

<%@ 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: Я переместил код в сервлет, и он все еще не работал. Я изменил кучу других вещей, так что вот последний нерабочий код:

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:

Это код сервлета, который я на самом деле работаю. Спасибо всем!

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

Ответы [ 7 ]

6 голосов
/ 19 июня 2009

Zips - это двоичные файлы, поэтому они не подходят для передачи в виде символьных данных. Также текст вне кода может повредить файл.

Используйте простой ванильный сервлет вместо JSP.

4 голосов
/ 19 июня 2009

JSP добавляет пробел к выводу. Я предлагаю вам перенести это на сервлет.

Кроме того, вы можете взглянуть на Удалять пробелы из вывода jsp , но я не уверен, что это не повлияет на сам вывод ZIP.

2 голосов
/ 19 июня 2009

Проблема в этом точном фрагменте находится на второй строке: у вас есть пустая строка вне тегов JSP, которая отправляется в браузер как HTML (то есть пустая строка в источнике HTML).

Будьте очень осторожны, чтобы удалить все, что не находится в <%%>, особенно пробелы (даже перевод строки), или следуйте советам в другом месте и используйте сервлет:)

1 голос
/ 19 июня 2009

Ваш код сервлета не работает, потому что вы выводите свой поток в response.getWriter(), что, как отмечали другие, относится к символьным данным . Я цитирую Javadoc:

PrintWriter getWriter() throws IOException
Возвращает объект PrintWriter, который может отправлять текстовый символ клиенту. PrintWriter использует кодировку символов, возвращаемую методом getCharacterEncoding ()

Мало того, вы даже не записываете байтовый массив в Writer, вы записываете результаты ByteArrayOutputStream.toString(), который также выполняет преобразование символов ~

Вы хотите использовать response.getOutputStream (), что-то вроде:

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

А затем запишите в него содержимое байтов вашего файла.

0 голосов
/ 19 июня 2009

Я бы также предложил использовать простой сервлет и счел бы ответом Роберта Мунтяну правильным, но вы можете сделать это и в своем JSP. Проблема не в добавленном пробеле, а в том, что неявная переменная "out" является экземпляром JSPWriter, а Writer - для символов, а не для байтов. Попробуйте использовать response.getOutputStream () и прямо на нем, это должно работать. Вы получите Исключение, сообщающее, что кто-то другой уже получил OutputStream, но вы можете проигнорировать его.

Но, как я уже сказал, использование сервлета будет намного чище.

0 голосов
/ 19 июня 2009
bufferedReader = new BufferedReader(new FileReader(zipLocation));

Помимо проблемы с сервлетами / JSP, эта строка повреждает ваши данные со 100% достоверностью. Он попытается интерпретировать двоичные данные как текст, используя кодировку платформы по умолчанию, что означает, что около половины байтов в файле заменены на «неизвестный символ».

Байты и строки не одно и то же!

0 голосов
/ 19 июня 2009

Считыватели, как правило, для символьных потоков, если я правильно помню - вы могли бы попробовать что-то более похожее на ByteArrayOutputStream? Кроме того, JSP действительно может повредить вывод, как прокомментировали другие.

...