2

What I want to do, is to create a zip file in nodeJs and later extract it through Java code(An already written Java program to work on the zip).

I am able to create zip file in nodeJs using jszip but my java code is unable to extract that zip file(Though my finder can extract it, even my extract code in nodeJs also works).

nodeJs code to create zip:

this.zip = function (sourceDirectory, zipFile, excludParent) {
        var zip = new JSZip();

        var list = getFiles(sourceDirectory, excludParent);
        for (var i = 0; i < list.length; i++) {
            var obj = list[i];
            if(typeof(obj.source) == "undefined"){
                if (excludParent)
                    zip.folder(obj.target.substring(obj.target.indexOf("/") + 1));
                else
                    zip.folder(obj.target);
            }else {
                if (excludParent)
                    zip.file(obj.target.substring(obj.target.indexOf("/") + 1), fs.readFileSync(obj.target), {base64: true});
                else
                    zip.file(obj.target, fs.readFileSync(obj.target), {base64: true});
            }
        }
        zip.generateNodeStream({type:'nodebuffer', streamFiles:true, compressionOptions:'DEFAULT'})
            .pipe(fs.createWriteStream(zipFile))
            .on('finish', function () {
                console.log(zipFile + " written.");
            })
    };

    var getFiles = function (sourceDirectory, excludeParent) {
        var list = [];
        if (excludeParent) {
            if (fs.lstatSync(sourceDirectory).isDirectory()) {
                var fileList = fs.readdirSync(sourceDirectory);
                for (var i = 0; i < fileList.length; i++) {
                    list = list.concat(getFiles_(sourceDirectory + sep, fileList[i]));
                }
            }
        } else {
            list = getFiles_("", sourceDirectory);
        }
        return list;
    };


    var getFiles_ = function (parentDir, path) {
        var list = [];

        if (path.indexOf(".") == 0) return list;
        if (fs.lstatSync(parentDir + path).isDirectory()) {
            list.push({target: parentDir + path});

            var fileList = fs.readdirSync(parentDir + path);
            for (var i = 0; i < fileList.length; i++) {
                list = list.concat(getFiles_(parentDir + path + sep, fileList[i]));
            }
        } else {
            list.push({source: parentDir + path, target: parentDir + path});
        }
        return list;
    };

Java code to extract file:

public void unzip(String zipFilePath, String destDirectory) throws IOException {
        File destDir = new File(destDirectory);
        if (!destDir.exists()) {
            destDir.mkdir();
        }
        ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
        ZipEntry entry = zipIn.getNextEntry();
        // iterates over entries in the zip file
        while (entry != null) {
            String filePath = destDirectory + File.separator + entry.getName();
            if (!entry.isDirectory()) {
                // if the entry is a file, extracts it
                extractFile(zipIn, filePath);
            } else {
                // if the entry is a directory, make the directory
                File dir = new File(filePath);
                dir.mkdirs();
            }
            zipIn.closeEntry();
            entry = zipIn.getNextEntry();
        }
        zipIn.close();
    }

This code throws following stacktrace:

java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor
    at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:310)
    at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
    at module.builder.ZipUtility.unzip(ZipUtility.java:57)
    at module.builder.DataPatcher.unZipAndroidImageFiles(DataPatcher.java:624)
    at module.builder.DataPatcher.patchAndroid(DataPatcher.java:145)
    at module.builder.FXMLDocumentController$5.call(FXMLDocumentController.java:324)
    at module.builder.FXMLDocumentController$5.call(FXMLDocumentController.java:312)
    at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:745)

This java code works fine if i create a zip file through an application (i.e winzip, winrar, zip made by finder etc.) but it throws ava.util.zip.ZipException: only DEFLATED entries can have EXT descriptor while extracting zip made through above mentioned nodeJs method.

2
  • You could try using Apache Commons Compress or at least read the documentation on the linked page which should explain some things. One is that data descriptors only work reliably when using deflated entries and I'd guess jszip always writes them. Maybe you can change the compressionOptions you're passing in your nodejs code to only use deflated entries. Commented Jun 29, 2017 at 9:56
  • This is known problem of Java: bugs.openjdk.java.net/browse/JDK-8143613 Commented Jan 17, 2019 at 9:20

1 Answer 1

2

I ran into the same problem today.

The issue is with the streamFiles:true passed as an option to zip.generateNodeStream(). From the docs:

When this options is true, we stream the file and use data descriptors at > the end of the entry. This option uses less memory but some program might > not support data descriptors (and won’t accept the generated zip file).

Removing the streamFiles:true option should work as long as you are not worried about memory usage.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.