Johan Johan - 1 month ago 13
Javascript Question

Uncompress a file with JavaScript

I need to load a json file into a Javascript container. On the user's browser, the json file is loaded into the Javascript library which processes the data. However, this file is getting quite large (10MB) but if I compress it I can get it down to 100KB.

I therefore want to compress the file on the server, download it using ajax, uncompress it and load it into my javascript container.

Generating the zip file is easy. What I'm struggling with is downloading the file and uncompressing it. I found a library called zip.js. I've followed their example, but I just can't get it to work. I think the way I'm loading the file is incorrect.

This is what I currently have:

var file_data = $.ajax({
url: "/path/to/file.zip",
async: false
}).responseText;

zip.createReader(new zip.TextReader(file_data), function(reader) {
// get all entries from the zip
reader.getEntries(function(entries) {
if (entries.length) {
// get first entry content as text
entries[0].getData(new zip.TextWriter(), function(text) {
// text contains the entry data as a String
console.log(text);
// close the zip reader
reader.close(function() {
// onclose callback
});

}, function(current, total) {
// onprogress callback
});
}
});
}, function(error) {
// onerror callback
console.log(error);
});


The error I get is:


File format is not recognized.


I also tried the BlobReader without success and the HttpReader class is not working for me, I get


zip.HttpReader is not a constructor

Answer

This is where you are doing wrong

var file_data = $.ajax({
    url: "/path/to/file.zip",
    async: false
}).responseText;
  • first of all async is bad practice and deprecated don't use it
  • second: jQuery's ajax don't handle binary so well. it always wants to treat everything as string which will cuz the binary to be parsed and transformed by the browser
    you don't want that. Your zip data will be corrupted

you should retrive the raw binary as is using either xhr.responseType = 'blob'

or using the new fetch api

fetch('file.zip').then(res => res.blob()).then(unzipBlob)

So forget jQuery...

If you want a synchronous feeling then you should use async/await + promises this is however only available in Blink (chrome/opera) you could also use babel

async function downlaod() {
   let res = await fetch(file)
   let file_data = await res.blob()

   // and so on...
}