2010-08-17 5 views
0

Я пытаюсь создать zip-файл с помощью сервлета, но он возвращает мне поврежденный zip-файл, вот код для функции zipcontents, я создаю zip, может кто-то помочь меня. Заранее спасибо.Загрузка zip-файла возвращает поврежденный 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(); 
    } 
} 

ответ

2

Слишком много проблем в коде. основные из них, которые являются источниками в:

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

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

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

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

ZipOutputStream output = new ZipOutputStream(response.getOutputStream()); 
zipFiles(directory.listFiles(), output); 
output.close(); 
+0

Спасибо, что решила проблема. – Vinay

+0

Добро пожаловать. – BalusC

0

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

0

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

Смежные вопросы