Jszip: Please provide exemple to get all files and their content

Created on 4 Nov 2016  路  3Comments  路  Source: Stuk/jszip

There are quite a lot of exemples with your library and this is great BUT
I think you should provide a exemple to get ALL the deflated files inside a zip.
(every exemple I see only process one file (with known name))

I think a lot of people are confused with the premises paradigm. And so am I.

I know how to get 1 file inside a zip, but get all contents look like a real mess.

questiosupport

Most helpful comment

To wait for multiple promises, you can use Promise.all(). This method transforms a list of promises into a promise of list.

Getting some known files is easy:

Promise.all([
  zip.file("Hello.txt").async("text"),
  zip.file("images/smile.gif").async("uint8array")
]).then(function(result) {
  var hello = result[0]; // text
  var smile = result[1]; // uint8array
  // or with ES6 destructuring assignment
  var [hello, smile] = result;
});

To resolve everything, whatever the input, you can:

  1. iterate on zip.files to create a list of entries
  2. map the list with async to get the list of promises
  3. use Promise.all to get a promise of list
  4. rework the list as necessary
// 1.
// this is like Object.values(zip.files) which is not yet implemented everywhere
var entries = Object.keys(zip.files).map(function (name) {
  return zip.files[name];
});

// 2.
var listOfPromises = entries.map(function(entry) {
  return entry.async("uint8array").then(function (u8) {
    // we bind the two together to be able to match the name and the content in the last step
    return [entry.name, u8];
  });
});

// 3.
var promiseOfList = Promise.all(listOfPromises);

// 4.
promiseOfList.then(function (list) {
  // here, list is a list of [name, content]
  // let's transform it into an object for easy access
  var result = list.reduce(function (accumulator, current) {
    var currentName = current[0];
    var currentValue = current[1];
    accumulator[currentName] = currentValue;
    return accumulator;
  }, {} /* initial value */);

  console.log(result);
});

I know promises have a learning curve (the ES7 async/await syntax will help, in the future). Fixing #281 will help here (sync generate means sync content).

All 3 comments

To wait for multiple promises, you can use Promise.all(). This method transforms a list of promises into a promise of list.

Getting some known files is easy:

Promise.all([
  zip.file("Hello.txt").async("text"),
  zip.file("images/smile.gif").async("uint8array")
]).then(function(result) {
  var hello = result[0]; // text
  var smile = result[1]; // uint8array
  // or with ES6 destructuring assignment
  var [hello, smile] = result;
});

To resolve everything, whatever the input, you can:

  1. iterate on zip.files to create a list of entries
  2. map the list with async to get the list of promises
  3. use Promise.all to get a promise of list
  4. rework the list as necessary
// 1.
// this is like Object.values(zip.files) which is not yet implemented everywhere
var entries = Object.keys(zip.files).map(function (name) {
  return zip.files[name];
});

// 2.
var listOfPromises = entries.map(function(entry) {
  return entry.async("uint8array").then(function (u8) {
    // we bind the two together to be able to match the name and the content in the last step
    return [entry.name, u8];
  });
});

// 3.
var promiseOfList = Promise.all(listOfPromises);

// 4.
promiseOfList.then(function (list) {
  // here, list is a list of [name, content]
  // let's transform it into an object for easy access
  var result = list.reduce(function (accumulator, current) {
    var currentName = current[0];
    var currentValue = current[1];
    accumulator[currentName] = currentValue;
    return accumulator;
  }, {} /* initial value */);

  console.log(result);
});

I know promises have a learning curve (the ES7 async/await syntax will help, in the future). Fixing #281 will help here (sync generate means sync content).

Thank you.
This is so much more detailed that I'd have expected.
I think this would be perfect for the documentation

This helps me to fix my ugly version. I found the Promise.all "trick" but this was still a mess because I didn't think of returning array with both content AND entry names. After reading it now looks quite obvious.

In step 1, maybe you could add a comment about what will be returned for DIR (an empty "uint8array" ?) and how (un)usefull it would be to filter out using the dir property.

Is there some good practice / tricks to know how to tell if a file is text (plain,(x)html,xml...) or binary or should this be handled by the dev ? (I see there's a _dataBinary but its name suggests it is private and it looks always true even for xhtml)

Encore merci David

In step 1, maybe you could add a comment about what will be returned for DIR (an empty "uint8array" ?) and how (un)usefull it would be to filter out using the dir property.

A directory doesn't have any content (it _contains_ files, but doesn't have any data attached to it), you will get an empty Uint8Array.
If you are only interested in files content, directories are not really useful and you can filter them out. It really depends on what you want to do with the result. I also forgot to remove them when I wrote my answer !

Is there some good practice / tricks to know how to tell if a file is text (plain,(x)html,xml...) or binary or should this be handled by the dev ? (I see there's a _dataBinary but its name suggests it is private and it looks always true even for xhtml)

_dataBinary is an internal flag to know how the content is stored (and, if you ask for a string, if we should utf8-decode it). A zip file doesn't contain the mime type of each entry (or any flag about it): I'm afraid you will need to check each file name extension.

Encore merci David

Glad I could help :-)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mikeiasNS picture mikeiasNS  路  5Comments

carloscarcamo picture carloscarcamo  路  5Comments

RUSHt picture RUSHt  路  5Comments

rushglen picture rushglen  路  4Comments

davejack1 picture davejack1  路  4Comments