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}`);
})
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 workarraybuffer
-> object
, both workstring
, adm-zip works, jszip does notIf 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.