DEV Community

C Jordi
C Jordi

Posted on

Don't Make Users Click 100 Times: How to Package and Download Multiple Files in JavaScript

So you've built a cool web app. Maybe it's an image filter, a report generator, or a data converter. Your app generates files for the user—which is great! But what happens when it needs to generate dozens or even hundreds of files at once?

Nobody wants to click "Download" 100 times. It's a terrible user experience.

Imagine a tool that extracts frames from a video. A short, 10-second clip could easily produce 300 individual image files. A practical example of this is a tool I found called https://videotoframes.com/, which handles this exact scenario. The challenge isn't just generating the files, but delivering them to the user in a sane way.

Today, we'll solve this problem by learning how to bundle multiple files into a single .zip archive, right in the browser, using JavaScript. No server required!

The Tool for the Job: JSZip
To accomplish this, we'll use a fantastic little library called JSZip. It's lightweight, has no dependencies, and its API is incredibly simple to understand.

First, you need to include the library in your project. You can either install it via npm (npm install jszip) or just link to it via a CDN for a quick demo.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

The Logic: Step-by-Step

Our goal is to take a collection of "files" (which can be simple text, image data, etc.) and package them for a single download.

Step 1: Create a new JSZip instance

This is our "virtual" zip file that we'll add files to.

const zip = new JSZip();
Enter fullscreen mode Exit fullscreen mode

Step 2: Add files to the archive

You can add files from various sources. The .file() method is your best friend here.

// Add a simple text file
zip.file("hello.txt", "Hello World\n");

// Add another file in a folder
const folder = zip.folder("my_folder");
folder.file("data.json", '{"name":"John Doe"}');
Enter fullscreen mode Exit fullscreen mode

You can also add binary data, like images. If you have an image as a Base64 string, you can add it like this:

// This is a tiny 1x1 transparent pixel in Base64
const imageData = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
zip.file("images/pixel.gif", imageData, {base64: true});
Enter fullscreen mode Exit fullscreen mode
// This is a tiny 1x1 transparent pixel in Base64
const imageData = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
zip.file("images/pixel.gif", imageData, {base64: true});
Enter fullscreen mode Exit fullscreen mode

## Step 3: Generate the Zip file

Once you've added all your files, you ask JSZip to generate the final .zip blob. This is an asynchronous process.

zip.generateAsync({type:"blob"}).then(content => {
  // 'content' is the zip file as a Blob
  // Now we can trigger the download...
});

Enter fullscreen mode Exit fullscreen mode

Conclusion

And there you have it! A simple, elegant solution to a common UX problem. By packaging files client-side, you reduce server load and give your users a much better experience.

Whether your app generates invoices, photo galleries, or extracts hundreds of frames from a video, this technique is a must-have in your developer toolbox.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.