0

I am generating a zip file using the module archiver. I want to wait for the zip file to be generated before proceeding further. Below is the relevant part of the code.

// create a file to stream archive data to.
const archiver = require('archiver');
const fs =  require('fs');

async function zipcsv(zipPath) {
  let output = fs.createWriteStream(zipPath);
  let archive = archiver('zip', {
    zlib: { level: 9 } // Sets the compression level.
  });
  output.on('close', function() {
   return 'zip generating complete';
  });
  archive.pipe(output);
  archive.directory('exports/', false);
  archive.finalize();
}

module.exports.zipcsv = zipcsv;

zip = require('./zipcsv')
await zip.zipcsv(path);
console.log('futher processing');

I see futher processing on the console and the process does not wait for the zip to be generated and continues.

How can I ensure that the zip is generated and then further processing continues.

Thanks.

opensource-developer
  • 2,826
  • 4
  • 38
  • 88

2 Answers2

1

archive.finalize() means that the appending of sub-files in the zip file is completed, but it does not imply that the write streams have completed. The same has been mentioned in the README Code pointer of the node-archiver library.

There is also an issue around this but I don't see any action item being taken on this.

There are 2 ways to solve this:

  1. Use the callback methods to wait for the write stream to complete.
// set a variable to track completion
let isComplete = false; 

// set this variable to true in the callback methods 
output.on('close', function() {
  isComplete = true;
});

archive.finalize();

// after finalize() wait till isComplete is not set to true
while (!isComplete) {
  console.log("waiting...");
  await new Promise((resolve) => {
    setTimeout(resolve, 100);
  });
}

  1. You can use adm-zip which allows you to deal with zip files directly on disk or in memory buffers. It's also simpler to use compared to node-archiver library.

Sample usage:

// creating archives
var zip = new AdmZip();

// add file directly
var content = "inner content of the file";
zip.addFile("test.txt", Buffer.from(content, "utf8"), "entry comment goes here");
// add local file
zip.addLocalFile("/home/me/some_picture.png");
// get everything as a buffer
var willSendthis = zip.toBuffer();
// or write everything to disk
zip.writeZip(/*target file name*/ "/home/me/files.zip");
himan085
  • 21
  • 3
0

You need to use a Promise Function inside your async function. Then use resolve and reject instead of return.