The compressed (zipped) folder is invalid Java

I'm trying to zip files from server into a folder using ZipOutputStream. After archive download it can't be opened after double click. Error "The compressed (zipped) folder is invalid" occures. But if I open it from context menu - > 7zip -> open file it works normal. What can be reason of the problem?

sourceFileName="./file.txt"'
                    sourceFile = new File(sourceFileName);

                    try {
                        // set the content type and the filename
                       responce.setContentType("application/zip");
                        response.addHeader("Content-Disposition", "attachment; filename=" + sourceFileName + ".zip");
                        responce.setContentLength((int) sourceFile.length());


                        // get a ZipOutputStream, so we can zip our files together
                        ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream());

                        // Add ZIP entry to output stream.
                        outZip.putNextEntry(new ZipEntry(sourceFile.getName()));

                        int length = 0;
                        byte[] bbuf = new byte[(int) sourceFile.length()];

                        DataInputStream in = new DataInputStream(new FileInputStream(sourceFile));
                        while ((in != null) && ((length = in.read(bbuf)) != -1)) {
                            outZip.write(bbuf, 0, length);
                        }

                        outZip.closeEntry();
                        in.close();
                        outZip.flush();
                        outZip.close();

Upvotes: 4

Views: 8660

Answers (2)

Joop Eggen
Joop Eggen

Reputation: 109613

It could be that a close is missing. It could be that the path encoding in the zip cannot be handled by Windows. It might be that Windows has difficulty with the directory structure, or that a path name contains a (back)slash. So it is detective work, trying different files. If you immediately stream the zip to the HTTP response, then finish has to be called i.o. close.


After the code being posted:

The problem is the setContentLength giving the original file size. But when given, it should give the compressed size.

DataInputStream is not needed, and one should here do a readFully.

    responce.setContentType("application/zip");
    response.addHeader("Content-Disposition", "attachment; filename=file.zip");

     //Path sourcePath = sourceFile.toPath();
     Path sourcePath = Paths.get(sourceFileName);

     ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream(),
            StandardCharsets.UTF-8);

     outZip.putNextEntry(new ZipEntry(sourcePath.getFileName().toString()));
     Files.copy(sourcePath, outZip);
     outZip.closeEntry();

Either finish or closethe zip at the end.

     outZip.finish();
     //outZip.close();

     in.close();

I am not sure (about the best code style) whether to close the response output stream already oneself. But when not closing finish() must be called, flush() will not suffice, as at the end data is written to the zip.

For file names with for instance Cyrillic letters, it would be best to add a Unicode charset like UTF-8. In fact let UTF-8 be the Esperanto standard world-wide.

A last note: if only one file one could use GZipOutputstream for file.txt.gz or query the browser's capabilities (request parameters) and deliver it compressed as file.txt.

Upvotes: 4

Hot Licks
Hot Licks

Reputation: 47759

7Zip can open a wide variety of zip formats, and is relatively tolerant of oddities. Windows double-click requires a relatively specific format and is far less tolerant.

You need to look up the zip format and then look at your file (and "good" ones) with a hex editor (such as Hex Editor Neo), to see what may be wrong.

(One possibility is that you're using the wrong compression algorithm. And there are several other variations to consider as well, particularly whether or not you generate a "directory".)

Upvotes: 4

Related Questions