1

I would like to download and unzip a folder with JSZip, I installed it with this npm package. JSZip is unable to do so, complaining about corrupted zip or unexpected signature.

There are many questions related to jszip. None of them answer my specific question, but for the sake of completeness, I'm listing a few references here:

As a test scenario, I have created two zip files, called folder.zip and text.zip. text.zip is a zipped txt file, folder.zip is a zipped folder, containing a txt file. Both have been zipped by the command line, in Ubuntu.

I'm hosting them with the npm package serve. They are accessible on localhost: http://localhost:5000/test.zip

Here is my code, it's typescript, the compiled Javascript is executed with node:

import axios from 'axios';
import * as JSZip from 'jszip';
axios.get(
    "http://localhost:5000/text.zip",
    //"http://localhost:5000/folder.zip",
    { responseType: "blob" })
    .then((response) => {

        let zip = new JSZip();
        zip.loadAsync(response.data).then((value) => {
            console.log('jszip unzipped response.data');
            value.forEach((path, file) => {
                console.log(path);
            })
        }).catch((e) => {
            console.log(`jszip failed on response.data: ${e}`);
        })

        let buffer = Buffer.from(response.data, 'binary');
        zip.loadAsync(buffer).then((value) => {
            console.log('jszip unzipped buffer');
            value.forEach((path, file) => {
                console.log(path);
            })
        }).catch((e) => {
            console.log(`jszip failed on buffer: ${e}`);
        })

    }).catch((reason) => {
        console.log(`axios request failed: ${reason}`);
    })

The text.zip file can be unzipped without problems. But when I try to unzip the folder, it fails. The error message is:

jszip failed on response.data: Error: Corrupted zip or bug: unexpected signature (\x00\x50\x4B\x07, expected \x50\x4B\x03\x04)

For comparison, I'm doing the same with adm-zip. This works for both the zipped file and the zipped folder. adm-zip only works when it is given a buffer though. That's why I also tried passing a buffer to jszip.

import axios from 'axios';
import * as AdmZip from 'adm-zip';
axios.get(
    "http://localhost:5000/folder.zip",
    { responseType: "blob" })
    .then((response) => {


        let buffer = Buffer.from(response.data, 'binary');
        let admzip = new AdmZip(buffer);
        let zipEntries = admzip.getEntries();
        zipEntries.forEach(element => {
            console.log(element.entryName);
        })

    }).catch((reason) => {
        console.log(`axios request failed: ${reason}`);
    })
oguz ismail
  • 1
  • 16
  • 47
  • 69
lhk
  • 27,458
  • 30
  • 122
  • 201

2 Answers2

1

Seems JSZip is a bit incomplete yet, according to it bugtracker (lots and generic errors present yet). About your error, there is another very similar: https://github.com/Stuk/jszip/issues/489 but i'm sure there are anothers.

So answer seems to be: JSZip is yet not-production-ready library at least for generic cases, and does not support it yet.

user1039663
  • 1,230
  • 1
  • 9
  • 15
  • ouch, the github issue list looks scary. Thanks for pointing this out, I will steer away from jszip. It's really strange though, according to npm stats, it's much much more used than adm-zip or archiver. Also, for the zipping part, it relies on a third-party library called paco. And that one looks very polished. – lhk Feb 28 '20 at 11:07
  • before accepting your answer, there's something else I would like to try though, to see if it unzips the folder. – lhk Feb 28 '20 at 11:08
  • I would use only for controlled scenarios, for example if you always generate the zip files. In that case if it works for one set, it should be working as long as you dont change very far the zip structure. However use it for ZIPs generated by the user... maybe there are other better alternatives, specially onserver environments. – user1039663 Mar 01 '20 at 03:24
0

The problem seems to be related to arraybuffer vs blob.

Depending on the configuration of the http request, the data field in the axios response will contain different values.

In the following code:

let responseType = 'blob'

axios.get(
    "http://localhost:5000/folder.zip",
    { responseType: responseType })
    .then((response) => {
        console.log(typeof(response.data);
        //...

the following pairs are possible:

  • blob -> string, adm-zip works, jszip does not work
  • arraybuffer -> object, both work
  • not specified -> string, adm-zip works, jszip does not

If the data has type string, adm-zip only works if it is manually converted into a Buffer.

If the result type is already a buffer, both work without any conversions.

lhk
  • 27,458
  • 30
  • 122
  • 201