12

I want to convert multiple files to a compressed zip file on node.js.

I tried the following code:

var archiver = require('archiver');
var fs = require('fs');
var StringStream = require('string-stream');

http.createServer(function(request, response) {
    var dl = archiver('data');
    dl.pipe(response);
    dl.append(new fs.createReadStream('test/fixtures/test.txt'), {
        name: 'stream.txt', date: testDate2
    });
    dl.append(new StringStream("Ooh dynamic stuff!"), {
        name : 'YoDog/dynamic.txt'
    });
    dl.finalize(function(err) {
        if (err)
            res.send(200000)
    });
}).listen(3500);
ndeverge
  • 21,378
  • 4
  • 56
  • 85
Kusuma Jammula
  • 121
  • 1
  • 1
  • 7
  • i'm not getting above code so pls tell me examples which are user friendly to understand – Kusuma Jammula Aug 09 '13 at 07:41
  • Have a look [at this example](https://github.com/ctalkington/node-archiver/blob/master/examples/pack-zip.js). It works for me. – mutil Aug 09 '13 at 07:50
  • is this code will alow multiple files and zip those? – Kusuma Jammula Aug 09 '13 at 07:51
  • It will compress multiple files to a .zip, yes. – mutil Aug 09 '13 at 07:55
  • hi mutil having doubt in the example in the above link i dint understand what is example-output.zip in var output = fs.createWriteStream(__dirname + '/example-output.zip'); pls explain me if possible – Kusuma Jammula Aug 09 '13 at 09:18
  • and getting error as ENOENT app crashed waiting for file changes before starting – Kusuma Jammula Aug 09 '13 at 09:28
  • `example-output.zip` is the name of the zip file you will get after compression. `ENOENT` error means that the specified files (fixtures/file1.txt & fixtures/file2.txt) were not found. Change `var file1` and `var file2` to the path of the files you want to compress. – mutil Aug 09 '13 at 09:40
  • mutil had got the zip file thank you still having some doubt – Kusuma Jammula Aug 09 '13 at 10:42
  • if i use __dirname + "filename" it shows to directory path and i need to put those file to specific path but i dont want to do that i want the to give the path dirictly – Kusuma Jammula Aug 09 '13 at 12:04

3 Answers3

26

There is a much simpler solution with the archiver module:

var fs = require('fs');
var archiver = require('archiver');
var output = fs.createWriteStream('./example.zip');
var archive = archiver('zip', {
    gzip: true,
    zlib: { level: 9 } // Sets the compression level.
});

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

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

// append files
archive.file('/path/to/file0.txt', {name: 'file0-or-change-this-whatever.txt'});
archive.file('/path/to/README.md', {name: 'foobar.md'});

// wait for streams to complete
archive.finalize();

It also supports tar archives, just replace 'zip' by 'tar' at line 4.

I get no credit for this code, it's just part of the README (you should check it out for other means of adding stuff into the archive).

Neat package, and it's probably the only one that's still being maintained and documented properly.

Aaron Meese
  • 1,670
  • 3
  • 22
  • 32
Overdrivr
  • 6,296
  • 5
  • 44
  • 70
  • i am also doing like this but it will throws an error like queue closed at archive.file...I dont know why it will occur so pls tell the answer – Prakash Mar 06 '19 at 07:16
  • Open a new question with your code + error stack. You can share the link here, i'll have a look – Overdrivr Mar 06 '19 at 09:50
  • ya sure i am already raised that question..Here the link is https://stackoverflow.com/questions/55001614/why-queue-closed-error-occours-at-archiver-file-in-nodejs – Prakash Mar 06 '19 at 10:05
  • The answer provided by Leonardo in your post is correct, this is a simple async issue. – Overdrivr Mar 06 '19 at 11:54
  • 1
    I'm confused by archiver [readme](https://github.com/archiverjs/node-archiver) which 1) places `archive.pipe(output)` *before* appending files and `archive.finalize()` (shouldn't it be *afterwards*?), 2) calls `archive.finalize()` as if multiple `archive.file()` operations are synchronous and it will just wait for them to finish, 3) has `end` and `close` handlers on the writeable `output` stream. Questions: Are the `archive.file()` operations actually synchronous? Does `archive.finalize()` trigger `archive.pipe(output)`? How does `archive` know when no more files are going to be added? – user1063287 Aug 04 '19 at 10:56
4

For zipping up multiple files, you can use this utility method I wrote with the archiver module:-

var zipLogs = function(working_directory) {
    var fs = require('fs');
    var path = require('path');
    var output = fs.createWriteStream(path.join(working_directory, 'logs.zip'));
    var archiver =  require('archiver');
    var zipArchive = archiver('zip');

    zipArchive.pipe(output);
    zipArchive.bulk([{src: [path.join(working_directory, '*.log')],  expand: true}]);
    zipArchive.finalize(function(err, bytes) {
        if (err)
            throw err;

    console.log('done:', base, bytes);
    });
}

This for example, zips up all the log files in a particular directory.

WaughWaugh
  • 1,012
  • 10
  • 15
-3

To Compress the text file using node js

var fs=require('fs');
var Zlib=require('zlib');
fs.createReadStream('input.txt').pipe(Zlib.createGzip()).pipe(fs.createWriteStream('input.txt.gz'));