How to make multiple ZIP files into single zip file in JSZip(React Native)?

I have used JSzip for my project to provide ZIP file downloads. I came around some requirement which requires multiple ZIP files to be inside a single ZIP file. I have tried multiple ways to achieve this but still can’t move forward as it downloads a empty ZIP only

I have attached my code here

downLoadFilesAsZip = async(item) => {
const zip1 = new JSZip();
for (const index in item.docLinks) {
  const url = item.docLinks[index];
  let linkParts = url.split("?");
  let filename = linkParts[0].substring(linkParts[0].lastIndexOf('/')+1);
  console.log("indexFiles",index);
  const response = await axios({
    url: url,
    method: 'GET',
    responseType: 'blob',
    headers: {
      'Content-Type': 'application/json',
    }
  });
  zip1.file(filename,response.data);

}
await zip1.generateAsync({ type: 'blob' })
  .then((blob) => {
    saveAs(blob, `${item.type}/${item.name}.zip`)
  })

}

downLoadAllAsZip = () => {
  {
    this.state.docGroups.length !== 0 && this.state.docGroups.map((item) => {
      if(item.docLinks !== null && item.docLinks.length > 0){
          return(
            this.downLoadFilesAsZip(item)
          );
      }
    })
  }  
}

This below code gives 10 to 15 separate zip file downloads

And I have a button where I pass my input to this function downLoadAllAsZip()

It is okay to have multiple folders instead of mutiple zip also but it has to be inside a single ZIP file.

To achieve the goal of having multiple ZIP files (or folders) inside a single ZIP file, you need to modify your code so that you are creating nested directories or ZIPs within a single ZIP archive instead of creating separate ZIP files for each item in the docGroups. Essentially, you want to add each zip1 (which contains the files for each item) as a separate file (or folder) in a master ZIP.

Here’s an updated approach to modify your code so that you can create a single ZIP file containing multiple ZIP files or folders inside it:

Solution: Add Multiple ZIPs (or folders) to a Master ZIP

Instead of calling this.downLoadFilesAsZip(item) for each item, you will call it and then add the resulting ZIP blob as a file in the main zip2 (the master ZIP file).

Updated Code:

downLoadFilesAsZip = async (item) => {
  const zip1 = new JSZip();
  for (const index in item.docLinks) {
    const url = item.docLinks[index];
    let linkParts = url.split("?");
    let filename = linkParts[0].substring(linkParts[0].lastIndexOf('/') + 1);

    const response = await axios({
      url: url,
      method: 'GET',
      responseType: 'blob',
      headers: {
        'Content-Type': 'application/json',
      }
    });
    zip1.file(filename, response.data);
  }

  // Generate the ZIP file (zip1)
  const zipBlob = await zip1.generateAsync({ type: 'blob' });
  return zipBlob;
}

downLoadAllAsZip = async () => {
  const masterZip = new JSZip();  // Create a master ZIP file

  // Loop through each docGroup and add the corresponding ZIP file (zip1) to the master ZIP
  for (const item of this.state.docGroups) {
    if (item.docLinks !== null && item.docLinks.length > 0) {
      const zipBlob = await this.downLoadFilesAsZip(item);

      // Create a folder in the master ZIP for each docGroup or use the item name
      const folderName = `${item.type}/${item.name}.zip`;

      // Add the generated ZIP (zip1) as a file to the master ZIP
      masterZip.file(folderName, zipBlob);
    }
  }

  // Once all files (ZIPs) are added, generate the master ZIP
  masterZip.generateAsync({ type: 'blob' })
    .then((blob) => {
      // Trigger the download of the master ZIP file
      saveAs(blob, 'master.zip');
    });
}

Explanation of Changes:

  1. Main ZIP (masterZip): You now create a masterZip (a single zip file) where you’ll add all other ZIP files as individual files (or folders).
  2. downLoadFilesAsZip(item): This function still creates a ZIP file for each item. However, instead of triggering a separate download, you return the generated ZIP as a Blob.
  3. Adding ZIPs to masterZip: Each ZIP file (zip1 generated from downLoadFilesAsZip) is added to masterZip using masterZip.file(folderName, zipBlob). You can structure the file name or path within the master ZIP as needed, such as including a folder for each item.
  4. Final ZIP generation: Once all the individual ZIP files are added to masterZip, the masterZip.generateAsync({ type: 'blob' }) is called to generate the master ZIP, and then the saveAs(blob, 'master.zip') triggers the download of the final ZIP file containing everything.

Result:

  • The final downloaded file will be a single ZIP file (named master.zip).
  • Inside that file, each item from docGroups will have its own ZIP file, and the structure will look like:
    • master.zip
      • type1/item1.zip
      • type2/item2.zip
      • type3/item3.zip

You can adjust the folder naming scheme as required, but this structure will achieve your goal of having multiple ZIPs inside a single ZIP file.

Notes:

  • Ensure that saveAs() function (from FileSaver.js) is available in your project. If not, you can install it via npm install file-saver.
  • This approach works because JSZip supports adding files or blobs to a ZIP archive, and we can use that to include each generated ZIP file as a separate entry inside the main ZIP.