I have a zip folder downloaded from s3 bucket. Now I have a json file in my code, and I want to add my JSON file to an existing zip file using node js code.

Is there any pre existing module for doing this in node js?

I tried easy-zip, but I was not able to add the file to an existing zip-folder.

Any idea on this?

I cannot find any any library that will do this inline and modify an already finalized zip. Here's a brute force approach that goes through the following steps:

  1. Create Temp Directory
  2. Extract Zip to Temp Dir
  3. Delete Original Zip
  4. Build Archive and seed with Temp Dir
  5. Callback to append any additional files
  6. Finalize Archive
  7. Delete Temp Directory

It uses extract-zip to unpack the zip and archiver to bundle it back up.

You can see the full source code at this repo KyleMit/append-zip

appendZip.js

// require modules
const fs = require('fs');
const fsp = fs.promises
const archiver = require('archiver');
const extract = require('extract-zip')

async function appendZip(source, callback) {
    try {
        let tempDir = source + "-temp"

        // create temp dir (folder must exist)
        await fsp.mkdir(tempDir, { recursive: true })

        // extract to folder
        await extract(source, { dir: tempDir })

        // delete original zip
        await fsp.unlink(source)

        // recreate zip file to stream archive data to
        const output = fs.createWriteStream(source);
        const archive = archiver('zip', { zlib: { level: 9 } });

        // pipe archive data to the file
        archive.pipe(output);

        // append files from temp directory at the root of archive
        archive.directory(tempDir, false);

        // callback to add extra files
        callback.call(this, archive)

        // finalize the archive
        await archive.finalize();

        // delete temp folder
        fs.rmdirSync(tempDir, { recursive: true })

    } catch (err) {
        // handle any errors
        console.log(err)
    }
}

Usage

async function main() {
    let source = __dirname + "/functions/func.zip"

    await appendZip(source, (archive) => {
        archive.file('data.json');
    });
}

In the callback, you can append files to the archive using any of the methods available with node-archiver, for example:

// append a file from stream
const file1 = __dirname + '/file1.txt';
archive.append(fs.createReadStream(file1), { name: 'file1.txt' });

// append a file from string
archive.append('string cheese!', { name: 'file2.txt' });

// append a file from buffer
const buffer3 = Buffer.from('buff it!');
archive.append(buffer3, { name: 'file3.txt' });

// append a file
archive.file('file1.txt', { name: 'file4.txt' });

// append files from a sub-directory and naming it `new-subdir` within the archive
archive.directory('subdir/', 'new-subdir');

// append files from a sub-directory, putting its contents at the root of archive
archive.directory('subdir/', false);

// append files from a glob pattern
archive.glob('subdir/*.txt');

Further Reading