Загрузка zip-файла возвращает поврежденный zip-файл с использованием сервлетов - PullRequest
0 голосов
/ 17 августа 2010

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

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
    IOException {

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    res.setContentType("application/zip");
    res.setHeader("Content-Disposition", "attachment; filename=output.zip;");

    fsep = File.separator;
    rootDir = new File(getServletContext().getRealPath("Projects" + File.separator + "amrurta"));
    File list[] = rootDir.listFiles();
    zos = new ZipOutputStream(bout);
    zipContents(list, rootDir.getName() + fsep);
    zos.close();
    res.getWriter().println(bout.toString());
}

public void zipContents(File[] file, String dir) {
    // dir - directory in the zip file
    byte[] buffer = new byte[4096];
    try {

        for (int i = 0; i < file.length; i++) { // zip files
            if (file[i].isFile()) {
                fis = new FileInputStream(file[i]);
                zos.putNextEntry(new ZipEntry(dir + file[i].getName()));
                // shows how its stored
                // System.out.println(dir+file[i].getName());
                int bytes_read;
                while ((bytes_read = fis.read(buffer)) != -1)
                    zos.write(buffer, 0, bytes_read);

                fis.close();
            }
        } // for

        // create empty dir if theres no files inside
        if (file.length == 1)
            zos.putNextEntry(new ZipEntry(dir + fsep)); // this part is erroneous i think

        for (int i = 0; i < file.length; i++) { // zip directories
            if (file[i].isDirectory()) {
                File subList[] = file[i].listFiles();

                // for dir of varying depth
                File unparsedDir = file[i];
                String parsedDir = fsep + file[i].getName() + fsep; // last folder
                while (!unparsedDir.getParentFile().getName().equals(rootDir.getName())) {
                    unparsedDir = file[i].getParentFile();
                    parsedDir = fsep + unparsedDir.getName() + parsedDir;
                }
                parsedDir = rootDir.getName() + parsedDir; // add input_output as root

                zipContents(subList, parsedDir);
            }
        } // for

    } catch (IOException ioex) {
        ioex.printStackTrace();
    }
}

Ответы [ 3 ]

2 голосов
/ 17 августа 2010

В коде слишком много проблем.основные из них:

  1. zos объявлена ​​как переменная экземпляра сервлета.Это не потокобезопасный .Он был разделен между несколькими запросами.Вы рискуете, что последующий запрос перезапишет предыдущий, когда он не был завершен.

  2. Двоичное содержимое ZIP преобразуется в символьные данные с помощью bout.toString().Это определенно повредит двоичные данные.Вы должны записывать двоичные данные как двоичные данные, используя обычный цикл InputStream#read() / OutputStream#write().

  3. Код не вызывает zos.closeEntry() в конце каждой записи.

Я думаю, что № 2 является основной причиной.Вам не нужно ByteArrayOutputStream.Это всего лишь ненужный боров памяти.Просто оберните response.getOutputStream() в ZipOutputStream.

ZipOutputStream output = new ZipOutputStream(response.getOutputStream());
zipFiles(directory.listFiles(), output);
output.close();
0 голосов
/ 21 февраля 2013

Вы можете создать вот так ZipOutputStream zipOut = new ZipOutputStream(res. getOutputStream()); И каждая запись в формате zip, которую вы записываете в запись zip, будет передана обратно вызывающей стороне.

0 голосов
/ 27 сентября 2010

Еще одна возможная причина - разные версии JVM сервера приложений и компилятора, который компилирует сервлет.Очень редкая проблема, но очень трудно понять.

...