Creating & Serving Zip files with Nodejs

Zip files are the first solution we apply whenever we want to share multiple files or a large file with someone be it Gmail/Google Drive or your custom web service we all use Zip files to compress the data.

Zipping a file is of great benefits for you and the end-user both, sometimes for saving storage space or at times the actual network bandwidth.

So, in this article, we will be building a small application in node js which will download user-specific data in the form of a zip file.

For sake of simplicity, we are not adding any database or any session check to it, we will be using a JSON file for the user data, you can check that data here which I generated from mockaroo.

So let’s begin.

  • Setup

Create a new folder and run the below commands, we will be using jszip for creating zip files


npm init && npm i express && npm i jszip 

Add the below code to use express and some initializations, it will just bootstrap the things we need.


const express = require("express"),
  JSZip = require("jszip"),
  sample_data = require("./sample_data.json");

const app = express();
const zip = new JSZip();

  • Create a sample_data.json file

Create a new JSON file in the root of your project with the name sample_data.json, you can use this file for reference, we have generated this mock data using Mockaroo.

  • Create a new route

Let’s create a new route, which accepts user ID as a slug parameter.


app.get('/download-zip/:user_id', (req, res) => {
  let user_id = req.param.user_id;

This route is responsible for downloading the actual zip file with user-specific data.

  • Find User Data

Now, we have to find user data based on the user_id which we have received from the slug param, the method we will be using is the find() method.


let data = sample_data.find((x) => == user_id); 

We are now ready with the user data, we have to proceed with the last step which is of creating a file & wrap that in a zip file & download it.

  • Creating a zip file

So for the original zip file, we want the following folder structure, and the file name will be based on the user’s full name from our sample json file.

And, to create a folder or a file we can use the JSZip() instance that we created in the first step, and we can use folder() & file() method.


const zip = new JSZip();
// Below will create a with the following content
zip.file("", "This is a sample readme file"); 

you can create folders using the folder() method, and the best part is we can chain them all along.


// below will create a new folder with a new file filename.txt 
zip.folder("user_details").file(`filename.txt`, "Hello World!"); 

Now to make the zip downloadable, we have to encode the zip into base64 encoded ASCII string and serve it over our HTTP response.

We can utilize the zip.generateAsync() method which generates the base64 encoding of our zip file.


zip.generateAsync({ type: "base64" }).then((base64) => {
  console.log("Base64 Encoded Data:", base64);

And finally, we will consolidate all our code, and the following is our complete code.


const express = require("express"),
  JSZip = require("jszip"),
  sample_data = require("./sample_data.json");

const app = express();
const zip = new JSZip();

app.get("/download-zip/:user_id", (req, res) => {
  let user_id = req.params.user_id;
  let data = sample_data.find((x) => == user_id);
    .file(`${}_details.txt`, JSON.stringify(data, null, 2));
  zip.file("", "This is a sample readme file");
  zip.generateAsync({ type: "base64" }).then((base64) => {
    let zip = Buffer.from(base64, "base64");
    res.writeHead(200, {
      "Content-Type": "application/zip",
      "Content-disposition": `attachment;`,



After getting the base64 encoded data, we simply served it over the http response using res.writeHead() & res.end(), with the right content type for the zip file & the content-disposition header.

And we are done 🙂

The code repo can be found here.

Hope you enjoyed reading and learned something out of it, feel free to add your questions or thoughts in the comments.

Leave a Reply

Your email address will not be published. Required fields are marked *