Zip files / folders / zips from Remote URLs with JSZip

Was stuck on this for a little bit and managed to overcome the problem and wanted to share incase anyone else encounters this in the future.

The function is used as an onClick for a button on the site, when the button is clicked, it needs to grab all the corresponding .zip files from individual remote urls (a CMS) and bundle into a singular .zip to then be downloaded to the user.

See answer below for the code.

Thank you for sharing your solution! It’s always great to see others contributing solutions to common problems. If you want to help others who may come across the same issue, here’s a summarized version of your approach for creating a ZIP file from multiple remote URLs:

Problem:

You need to download multiple .zip files from individual remote URLs (like from a CMS), then bundle them into a single .zip file for the user to download.

Solution:

The solution involves using JSZip to gather all the .zip files from the provided URLs, add them to a master ZIP, and then allow the user to download it. Here’s the working code for that:

Code:

import JSZip from 'jszip';
import axios from 'axios';
import { saveAs } from 'file-saver';

async function downLoadFilesAsZip(item) {
  const zip1 = new JSZip();

  for (const url of item.docLinks) {
    const linkParts = url.split("?");
    const 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 for the current item
  const zipBlob = await zip1.generateAsync({ type: 'blob' });
  return zipBlob;
}

async function downLoadAllAsZip() {
  const masterZip = new JSZip();  // Master zip for the final download

  for (const item of this.state.docGroups) {
    if (item.docLinks && item.docLinks.length > 0) {
      const zipBlob = await this.downLoadFilesAsZip(item);
      
      // Add each zipBlob to the master zip
      const folderName = `${item.type}/${item.name}.zip`;  // Folder name for each docGroup
      masterZip.file(folderName, zipBlob);
    }
  }

  // Once all individual zips are added, generate the master zip
  const masterZipBlob = await masterZip.generateAsync({ type: 'blob' });

  // Trigger download of the master zip
  saveAs(masterZipBlob, 'master.zip');
}

Key Features:

  1. Multiple Remote .zip Files: The downLoadFilesAsZip function retrieves .zip files from individual URLs and adds them to a temporary ZIP (using JSZip).
  2. Master ZIP File: The downLoadAllAsZip function aggregates all these individual ZIP files into one master ZIP.
  3. Final Download: The final master.zip containing all the individual ZIP files (or folders) is generated and offered for download to the user.

Explanation:

  1. Fetching .zip Files: You use axios to fetch each .zip file from the remote URLs and store them as blobs.
  2. Bundling into a Master ZIP: Each .zip file is added to the master ZIP with a unique path or name, ensuring the structure is clear.
  3. User Download: After bundling, the saveAs function triggers the download of the master.zip file.

Final Thoughts:

This method is efficient for bundling multiple remote .zip files into a single download for the user. The use of JSZip ensures that the process remains entirely in JavaScript, avoiding the need for any external applications or server-side logic.

Thanks again for sharing your solution! It’s always helpful to know that others are tackling similar problems and overcoming them effectively.