Zip and compress files in JavaScript

OpenJavaScript 0

Last updated: November 14, 2023.

You can add multiple files to a zip file in JavaScript (and set a custom level of compression) using the JSZip library.

To import JSZip into your project, you can either add a CDN link like the one below to the head of your document or, if working with npm from the command line, run npm install jszip.

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

To create a zip file, you start by creating a new instance of the JSZip object and calling the file method on the result to add files:

const zip = new JSZip();

// Add files:
zip.file("filename.txt", "File data here");
zip.file("filename2.txt", "More file data here");

You can add a folder using the folder method and add files inside it by calling the file method on its result:

//... Same as above

const readmeFolder = zip.folder("readme");
readmeFolder.file("README.txt", "I am a readme");

To actually create the zip file, you need to call generateAsync on the zip object to which the files have been added.

Calling generateAsync returns a promise whose result is the zip file:

zip.generateAsync({ type: 'blob' })
.then((res) => {
  console.log(res); // The zip file
});

The object specifying a type for the zip file is required.

It is within this object that you can specify that you would like to add compression and specify a level:

zip.generateAsync({     
    type: "blob",
    compression: "DEFLATE", // Indicates should be compressed
    compressionOptions: {
        level: 9 // Between 1 (best speed) and 9 (best compression)
    }
})
.then((res) => {
  console.log(res);
});

Below is a complete example of zipping and compressing files selected by a user via an <input type="file"> element:

<input type="file" multiple>

<script>

    const input = document.querySelector('input');

    input.addEventListener('change', (e) => {

        const files = e.target.files;
        
        const zip = new JSZip();

        for (let i=0; i<files.length; i++) {
            zip.file(`file${i}`, files[i]);
        };

        zip.generateAsync({ 
            type:"blob",
            compression: "DEFLATE",
            compressionOptions: {
                level: 9
            }
        })
        .then(res => {
            
            console.log(res);
    
            // Comparing old and new sizes:
            let originalSize = 0;
            for (file of files) {
                originalSize += file.size;
            };

            console.log(`Original size of files: ${originalSize}`);
            console.log(`Compressed size of files: ${res.size}`);
        });

    });

</script>

You can initiate a user download of the zip file using the following code:

const a = document.createElement('a');
a.setAttribute('download', 'my_zip_file.zip');

const url = URL.createObjectURL(zip); // Create link to file in memory

a.href = url;
a.setAttribute('target', '_blank');

a.click(); // Simulates user click to initiate download

URL.revokeObjectURL(url);