How to read and create zip files in nodejs

As I’ve been working on a small project for the past few months, mostly related to backend processing – files, databases etc. The small part of the project needed the ability to read and write zip files. I found the jsZip npm package adequate for my requirement. This allows me to quickly read and write zip files.

Installation with npm is as usual.

npm install jszip

Reading zip files

First we will see how to read a zip file from your local directory. Assuming you have a file named ‘project.zip’ which includes a few JavaScript files.

var fs = require("fs");
var JSZip = require("jszip");
 
// read a zip file
fs.readFile("project.zip", function(err, data) {
    if (err) throw err;
    JSZip.loadAsync(data).then(function (zip) {
      files = Object.keys(zip.files);
      console.log(files);
    });
});

This will return the names of the files in the zip file.

[ 'file-monitor.js',
  'file-set.js',
  'filenamify.js',
  'form-data.js',
  'fuzzball.js',
  'gmail.js' ]

The general structure of the zip file object returned is given below.

{ files:
	{ 'file-monitor.js':
	   { name: 'file-monitor.js',
		 dir: false,
		 date: 2018-05-01T09:52:56.000Z,
		 comment: null,
		 unixPermissions: null,
		 dosPermissions: 32,
		 _data:
		  { compressedSize: 293,
			uncompressedSize: 612,
			crc32: -1393654514,
			compression: [Object],
			compressedContent: <Buffer 85 51 cd 4a 03 31 10 be 2f ec...
	26 98 a4 5d 44 7c 77 67 b2 dd 35 d0 83 87 10 32 f3 fd ... > },
		 _dataBinary: true,
		 options: { compression: null, compressionOptions: null } },
	  'file-set.js':

We read the filenames using the following.

files = Object.keys(zip.files);

To get additional details for each file we can do the following.

// Get additional details for the file 'file-monitor.js'
console.log(zip.files['file-monitor.js']);

Now we can iterate over all the files and display additional details for each.

// read a zip file
fs.readFile("project.zip", function(err, data) {
    if (err) throw err;
    JSZip.loadAsync(data).then(function (zip) {
      // Get list of filenames, which are also keys for additional details
      files = Object.keys(zip.files);
 
      for(i=0; i< files.length; i++){
          console.log(files[i] + " " + zip.files[files[i]].date);
      }
    });
});

To read the contents of a file in the zip archive you can use the following. Assume you have a ‘Hello.txt’ file in the zip archive with the content ‘Hello World!’.

// read a zip file
fs.readFile("project.zip", function(err, data) {
    if (err) throw err;
    JSZip.loadAsync(data).then(function (zip) {
 
      // Read the contents of the 'Hello.txt' file
      zip.file("Hello.txt").async("string").then(function (data) {
        // data is "Hello World!"
        console.log(data);
      });
 
    });
});

We are using the ‘string’ type here when reading the file, but you can use other types supported by jsZip.

Possible values for type :

base64 : the result will be a string, the binary in a base64 form.
text (or string): the result will be an unicode string.
binarystring: the result will be a string in ‘binary’ form, using 1 byte per char (2 bytes).
array: the result will be an Array of bytes (numbers between 0 and 255).
uint8array : the result will be a Uint8Array. This requires a compatible browser.
arraybuffer : the result will be a ArrayBuffer. This requires a compatible browser.
blob : the result will be a Blob. This requires a compatible browser.
nodebuffer : the result will be a nodejs Buffer. This requires nodejs.

Example:

zip.file("image.png").async("uint8array").then(function (u8) {
    // ...
});

All formats will not be supported on all OS platforms so check before using.

if (JSZip.support.string) {
        zip.file("Hello.txt").async("string").then(function (data) {
          // data is "Hello World!"
          console.log(data);
        });
     }

Writing zip files

Creating a zip file is a little involved as compared to reading a zip file.

var fs = require("fs");
var JSZip = require("jszip");
 
var zip = new JSZip();
 
// Add a top-level, arbitrary text file with contents
zip.file("Hello.txt", "Hello World\n");
 
// Create a directory within the Zip file structure
var img = zip.folder("images");
 
// Sample image data
imgData = 'R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7';
 
// Add a file to the 'images' directory, 
// and add an image with data URI as contents.
img.file("star.gif", imgData, {base64: true});
 
// JSZip can generate Buffers so you can do the following
zip.generateNodeStream({type:'nodebuffer',streamFiles:true})
   .pipe(fs.createWriteStream('out.zip'))
   .on('finish', function () {
       // JSZip generates a readable stream with a "end" event,
       // but is piped here in a writable stream which emits a "finish" event.
       console.log("out.zip written.");
    });

Leave a Reply

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