I'm using node-zipstream to create ZIP files in node.js. I've created a simple wrapper to create the illusion of a syncronous API when adding streams to the ZIP (included in the code below).
When using request streams, everything works as expected, but when I use file streams, the second stream becomes unreadable after the first is done.
var zipstream = require('zipstream');
var fs = require('fs');
function ZipQueue(out, options) {
var zip = zipstream.createZip(options);
zip.pipe(out);
var queue = new Array();
this.addFile = function(readStream, options) {
queue.push({stream: readStream, options: options});
}
this.runQueue = function(cb) {
for(var element in queue) {
queue[element].stream.on('error', function(err) {
console.dir(err);
})
}
function run() {
i++;
if (queue.length > i) {
console.log("Queue:");
console.dir(queue);
console.log("\n");
zip.addFile(queue[i].stream, queue[i].options, run);
}
else {
zip.finalize(cb);
}
}
var i = -1;
run();
}
}
var out = fs.createWriteStream('out.zip');
var q = new ZipQueue(out, { level: 1 });
q.addFile(fs.createReadStream("1.txt"), { name: 'files/1.txt' });
q.addFile(fs.createReadStream("2.txt"), { name: 'files/2.txt' });
q.runQueue(function(written) { console.log(written + ' total bytes written'); });
Console output:
>node zip.js
Queue:
[ { stream:
{ path: '1.txt',
fd: null,
readable: true,
paused: false,
flags: 'r',
mode: 438,
bufferSize: 65536,
_events: [Object] },
options: { name: 'files/1.txt' } },
{ stream:
{ path: '2.txt',
fd: null,
readable: true,
paused: false,
flags: 'r',
mode: 438,
bufferSize: 65536,
_events: [Object] },
options: { name: 'files/2.txt' } } ]
Queue:
[ { stream:
{ path: '1.txt',
fd: 4,
readable: false,
paused: false,
flags: 'r',
mode: 438,
bufferSize: 65536,
_events: [Object],
reading: false },
options:
{ name: 'files/1.txt',
version: 20,
bitflag: 8,
method: 8,
moddate: 1098783117,
offset: 0,
crc32: -137262718,
compressed: 7,
uncompressed: 5 } },
{ stream:
{ path: '2.txt',
fd: 5,
readable: false,
paused: false,
flags: 'r',
mode: 438,
bufferSize: 65536,
_events: [Object],
reading: false },
options: { name: 'files/2.txt' } } ]