1

Getting error: undefined as a listener instead of a function on line 13. Here zip.on('entry') isn't working. I am trying async await and catching the error in a catchAsync function. But the error is actually coming as unhandled rejection. Can you fix my code please.Original synchronous code belongs to this answer, https://stackoverflow.com/a/46967462/10693479

const StreamZip = require('node-stream-zip');
const fs = require('fs').promises;
const path = require('path');
const rmfr = require('rmfr');

module.exports = async (req, res, next) => {
  var zip = new StreamZip.async({
    file: `./tmp/my-uploads/${req.file.filename}`,
    storeEntries: true,
  });

  // entry functions
  const entry = await zip.on('entry');

  //create path
  var pathname = await path.resolve(
    `html-theme-uploads/${req.file.filename}`,
    entry.name
  );

  // check maliciously crafted path
  if (
    await /\.\./.test(
      path.relative(`html-theme-uploads/${req.file.filename}`, pathname)
    )
  ) {
    return res.status(201).json({
      status: 'Failed',
      message: `[Zip Warn]: Maliciously crafted paths in zip file:,
      ${entry.name}`,
    });
  }
  //get directories
  // if ('/' === entry.name[entry.name.length - 1]) {
  //   // console.log('[DIR]', entry.name);
  // }

  //create stream
  const stream = await zip.stream(entry.name);

  // example: print contents to screen
  //stream.pipe(process.stdout);

  // example: save contents to file

  await fs.mkdir(path.dirname(pathname), { recursive: true });
  await stream.pipe(await fs.createWriteStream(pathname));

  // on close delete macosx if there is one
  await zip.close();
  await rmfr(`html-theme-uploads/${req.file.filename}/__MACOSX/`);

  //delete uploaded zip after extracting
  await fs.unlink(`./tmp/my-uploads/${req.file.filename}`);

  //pass to next
  next();
};

  • Isn’t zip.on used to set up an event listener? i wouldn’t think you await it (or assign it to a variable). try zip.on("entry", () => /* code that runs when on entry happens */) – James Mar 27 '21 at 10:53
  • okay that runs but then createWriteStream isn't a function error comes – Abu Sayeed Mondal Mar 27 '21 at 10:55
  • Also will it still await to pass the next() function on last line? I wrote it like zip.on("entry", async (entry) => – Abu Sayeed Mondal Mar 27 '21 at 10:57

1 Answers1

0

I got the solution by using the extract method. Here is the full working code.

const StreamZip = require('node-stream-zip');
const fs = require('fs').promises;
const rmfr = require('rmfr');
const catchAsync = require('./catchAsync');

module.exports = catchAsync(async (req, res, next) => {
  var zip = new StreamZip.async({
    file: `./tmp/my-uploads/${req.file.filename}`,
    storeEntries: true,
  });

  await fs.mkdir(`html-theme-uploads/${req.file.filename}`);
  const count = await zip.extract(
    null,
    `./html-theme-uploads/${req.file.filename}`
  );
  console.log(`Extracted ${count} entries`);
  await zip.close();

  await rmfr(`html-theme-uploads/${req.file.filename}/__MACOSX/`);

  //delete uploaded zip after extracting
  await fs.unlink(`./tmp/my-uploads/${req.file.filename}`);

  //pass to next
  next();
});