1

I am trying to archive a folder using archiver, the path of the folder that i'd like to archive look like this :

Project
| app.js
| tmp
    |
     folderToArchive
            │file1.txt 
            │file2.txt 
            │file3.txt 

my server side code where the zip file will be generated look like this :

var archiver = require("archiver");

    app.get("/download/:folder", (req, res) => {
    
      var FolderName = req.params.folder;
      var zipName = FolderName + ".zip";
      var source = path.join(__dirname, "tmp", FolderName);
      var out = path.join(__dirname, "tmp", zipName);
    
    
      const archive = archiver('zip', { zlib: { level: 9 }});
      const stream = fs.createWriteStream(out);
    
      return new Promise((resolve, reject) => {
        archive
          .directory(source, false)
          .on('error', err => reject(err))
          .pipe(stream)
        ;
    
        stream.on('close', () => resolve());
        archive.finalize();
        console.log("zip file created");
      });
    
    });

The issue is when i run the app it will create an empty zip file in the right destination.

This is totally new for me and I'd like to understand why the zip file is empty ?

Regards

Community
  • 1
  • 1
anehme
  • 536
  • 1
  • 6
  • 18

2 Answers2

4

It could likely be the same reason that I had an empty archive, which is the main process ending before the archive get to write into zip.

Hence it should be wrapped in a promise, something like this:

    async function zipDirectory(source, dest) {
  const stream = fs.createWriteStream(dest);
  const archive = archiver('zip', { zlib: { level: 9 } });

  archive.on('error', function(err) {
  throw err;
  });

  await new Promise((resolve, reject) => {
    archive.pipe(stream);
    archive.directory(source, false);
    archive.on('error', err => {throw err;});
    archive.finalize();

    stream
        .on('close', function() {
        console.log(`zipped ${archive.pointer()} total bytes.`);
        resolve();
        });
  });
}
0

Tested the following code and it works:

const path = require('path');
const archiver = require('archiver');
const fs = require('fs');

const FolderName = "fol";
const zipName = FolderName + ".zip";
const source = path.join(__dirname, "tmp", FolderName);
const out = path.join(__dirname, "tmp", zipName);

const archive = archiver('zip', { zlib: { level: 9 }});
const stream = fs.createWriteStream(out);

archive
    .directory(source, false)
    .on('error', err => {throw err;})
    .pipe(stream);

stream.on('close', () => console.log("closed"));
archive.finalize();
console.log("zip file created");

So I suggest:

const path = require('path');
const archiver = require('archiver');
const fs = require('fs');

const archive = (folderName) => {
    const zipName = folderName + ".zip";
    const source = path.join(__dirname, "tmp", folderName);
    const out = path.join(__dirname, "tmp", zipName);

    const archive = archiver('zip', { zlib: { level: 9 }});
    const stream = fs.createWriteStream(out);

    archive
        .directory(source, false)
        .on('error', err => {throw err;})
        .pipe(stream);

    stream.on('close', () => console.log("closed"));
    archive.finalize();
    console.log("zip file created");
};

app.get("/download/:folder", (req, res) => {
    const folderName = req.params.folder;
    archive(folderName);
});
Horatiu Jeflea
  • 7,256
  • 6
  • 38
  • 67
  • the tmp folder and my app.js file are in the same directory so this why i am using __dirname – anehme Oct 10 '19 at 13:12