Create Zip Files with JavaScript

By  on  

While we're doing amazing things with JavaScript on the server side, it's important not to take our eyes off of some of the great stuff happening on the client side.  One such awesome project I recently discovered was JSZip:  a JavaScript library that allows you to easily generate ZIP files from the front-end.  And why is that useful?  You can allow users to select and download images from a gallery or just about anything else.  Let's have a look at how JSZip allows you to generate structured Zip files from the client side!

Start by grabbing the JSZip library , which happens to work in all major browsers.  Once the library is available within the page, generating a Zip file is really just a few lines of code:

var zip = new JSZip();

// Add an top-level, arbitrary text file with contents
zip.file("Hello.txt", "Hello World\n");

// Generate a directory within the Zip file structure
var img = zip.folder("images");

// Add a file to the directory, in this case an image with data URI as contents
img.file("smile.gif", imgData, {base64: true});

// Generate the zip file asynchronously
zip.generateAsync({type:"blob"})
.then(function(content) {
    // Force down of the Zip file
    saveAs(content, "archive.zip");
});

You can add individual files with custom names and contents, as well as arbitrary directories.  Once your contents are added, JSZip can asynchronously generate your Zip file and you can subsequently trigger download.

You can also load and read Zip files:
var read_zip = new JSZip();
// Load zip content; you'd use fetch to get the content
read_zip.loadAsync(content)
.then(function(zip) {
    // Read from the zip file!
    read_zip.file("hello.txt").async("string"); // a promise of "Hello World\n"
});

I really appreciate JSZip's simplicity.  There are more advanced and complicated libraries available, like zip.js, but JSZip will likely cover most use cases.  One great example of taking advantage of Zip files on the client side is in the Service Worker Cookbook: cache a Zip file locally, extract its contents, and serve within a service worker.  Whatever your use case, know that Zip files can be read and generated without any need for a server!

Recent Features

  • By
    CSS Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome...

  • By
    9 Mind-Blowing WebGL Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted 9 mind-blowing demos.  Another technology available...

Incredible Demos

  • By
    jQuery UI DatePicker:  Disable Specified Days

    One project I'm currently working on requires jQuery. The project also features a datepicker for requesting a visit to their location. jQuery UI's DatePicker plugin was the natural choice and it does a really nice job. One challenge I encountered was the...

  • By
    CSS Fixed Positioning

    When you want to keep an element in the same spot in the viewport no matter where on the page the user is, CSS's fixed-positioning functionality is what you need. The CSS Above we set our element 2% from both the top and right hand side of the...

Discussion

  1. Andrew Wooldridge

    Thank you so much for this! I am creating a web based RPG maker, and I needed a way to create zip archives. This is perfect!

  2. Steve Fu

    May I know if this solution works in Mobile / Tablet App?

  3. Hi, thanks for your article.

    Your missing one point, the saveAs function.

    Either, you can use FileSaver.js if you work with NodeJS (server side) mentionned in https://stuk.github.io/jszip/

    Or you can use the following function if you work on the client side only:

    function saveAs(blob, filename) {
      if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {
        return navigator.msSaveOrOpenBlob(blob, fileName);
      } else if (typeof navigator.msSaveBlob !== 'undefined') {
        return navigator.msSaveBlob(blob, fileName);
      } else {
        var elem = window.document.createElement('a');
        elem.href = window.URL.createObjectURL(blob);
        elem.download = filename;
        elem.style = 'display:none;opacity:0;color:transparent;';
        (document.body || document.documentElement).appendChild(elem);
        if (typeof elem.click === 'function') {
          elem.click();
        } else {
          elem.target = '_blank';
          elem.dispatchEvent(new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: true
          }));
        }
        URL.revokeObjectURL(elem.href);
      }
    }
    
  4. Gabriel

    What is ‘imgData’? how I can get this?

  5. This is _really cool_! I’m so excited to find out that the client-side code can now handle all these interesting little use-cases. I’m planning to combine this technique with html2canvas() to generate PNG files on the client and then Zip them together. What a wonderful time to be alive!

  6. Souvik

    How can I tweak this such that instead of downloading zip, I can just create the zip and send it to a server through ajax?

  7. Jerry

    From what I can tell imgData is a placeholder for a string of text that can be found inside image files. Getting a file to open up and give us that string is the problem.

    img.file('image.jpg', fs.readFileSync('image.jpg'));

    This might work if you have nodeJS installed on the server, but that involves installing something on the server. Is there a way to keep it all on the client side? That would be nice.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!