archiver
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -9,6 +9,13 @@ /* | ||
var tarArchiver = require('./archiver/tar'); | ||
var zipArchiver = require('./archiver/zip'); | ||
exports.createZip = function(opt) { | ||
var archiver = module.exports = {}; | ||
archiver.createTar = function(opt) { | ||
return new tarArchiver(opt); | ||
}; | ||
archiver.createZip = function(opt) { | ||
return new zipArchiver(opt); | ||
}; |
var stream = require('stream'); | ||
var util = require('util'); | ||
var inherits = require('util').inherits; | ||
function Archiver(opt) { | ||
var utils = require('../util/utils'); | ||
var Archiver = module.exports = function() { | ||
var self = this; | ||
@@ -15,9 +17,6 @@ | ||
self.files = []; | ||
self.options = opt || {}; | ||
} | ||
}; | ||
util.inherits(Archiver, stream.Stream); | ||
inherits(Archiver, stream.Stream); | ||
module.exports = Archiver; | ||
Archiver.prototype.pause = function() { | ||
@@ -43,3 +42,5 @@ var self = this; | ||
if (!self.readable || self.paused) { return; } | ||
if (self.readable === false || self.paused) { | ||
return; | ||
} | ||
@@ -55,3 +56,3 @@ if (self.queue.length > 0) { | ||
if (self.callback) { | ||
if (utils.lo.isFunction(self.callback)) { | ||
self.callback(self.fileptr); | ||
@@ -67,8 +68,8 @@ } | ||
Archiver.prototype.finalize = function(callback) { | ||
Archiver.prototype.addFile = function(source, data, callback) { | ||
// placeholder | ||
}; | ||
Archiver.prototype.addFile = function(source, file, callback) { | ||
Archiver.prototype.finalize = function(callback) { | ||
// placeholder | ||
}; |
@@ -1,16 +0,209 @@ | ||
var util = require('util'); | ||
var inherits = require('util').inherits; | ||
var zlib = require('zlib'); | ||
var Archiver = require('./core.js'); | ||
var crc32 = require('../util/crc32'); | ||
var utils = require('../util/utils'); | ||
var zipArchiver = function(opt) { | ||
Archiver.call(this, opt); | ||
var zipArchiver = module.exports = function(options) { | ||
var self = this; | ||
Archiver.call(self); | ||
options = self.options = utils.lo.defaults(options || {}, { | ||
comment: '', | ||
zlib: { | ||
level: 6 | ||
} | ||
}); | ||
if (utils.lo.isNumber(options.level)) { | ||
options.zlib.level = options.level; | ||
delete options.level; | ||
} | ||
}; | ||
util.inherits(zipArchiver, Archiver); | ||
inherits(zipArchiver, Archiver); | ||
module.exports = zipArchiver; | ||
var fileHeader = { | ||
format: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x04034b50}, | ||
{'field': 'versionNeededToExtract', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'flags', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'compressionMethod', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'lastModifiedDate', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE', 'default': 0}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'filenameLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'extraFieldLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'name', 'length': -1, 'type': 'string'}, | ||
{'field': 'extraField', 'length': -1, 'type': 'string'} | ||
], | ||
create: function(data) { | ||
var buffer = new Buffer(1024); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
this.format.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
if (value.field === 'name') { | ||
value.length = buffer.write(val, offset); | ||
buffer.writeUInt16LE(value.length, 26); | ||
} else if (value.field === 'extraField') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 28); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
return buffer.slice(0, offset); | ||
} | ||
}; | ||
var dataDescriptorHeader = { | ||
format: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x08074b50}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE'}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'} | ||
], | ||
create: function(data) { | ||
var buffer = new Buffer(16); | ||
var offset = 0; | ||
var val; | ||
this.format.forEach(function(value) { | ||
val = data[value.field] || value.default || 0; | ||
if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
return buffer; | ||
} | ||
}; | ||
var centralDirectoryHeader = { | ||
format: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x02014b50}, | ||
{'field': 'versionMadeBy', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'versionNeededToExtract', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'flags', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'compressionMethod', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'lastModifiedDate', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE'}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'filenameLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'extraFieldLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'commentLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'diskNumberStart', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'internalFileAttributes', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'externalFileAttributes', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'offset', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'name', 'length': -1, 'type': 'string'}, | ||
{'field': 'extraField', 'length': -1, 'type': 'string'}, | ||
{'field': 'comment', 'length': -1, 'type': 'string'} | ||
], | ||
create: function(data) { | ||
var buffer = new Buffer(1024); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
var nameLength; | ||
this.format.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
if (value.field === 'name') { | ||
value.length = buffer.write(val, offset); | ||
buffer.writeUInt16LE(value.length, 28); | ||
} else if (value.field === 'extraField') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 30); | ||
} else if (value.field === 'comment') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 32); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
return buffer.slice(0, offset); | ||
} | ||
}; | ||
var centralDirectoryFooter = { | ||
format: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x06054b50}, | ||
{'field': 'diskNumber', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'diskNumberStart', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directoryRecordsDisk', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directoryRecords', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directorySize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'directoryOffset', 'length': 4, 'type': 'UInt32LE'},, | ||
{'field': 'commentLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'comment', 'length': -1, 'type': 'string'} | ||
], | ||
create: function(data) { | ||
var buffer = new Buffer(512); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
this.format.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
if (value.field === 'comment') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 20); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
return buffer.slice(0, offset); | ||
} | ||
}; | ||
// local file header | ||
@@ -20,28 +213,8 @@ zipArchiver.prototype._pushLocalFileHeader = function(file) { | ||
file.version = 20; | ||
file.bitflag = (1<<3) | (1<<11); | ||
file.method = file.store ? 0 : 8; | ||
if (!file.date) { file.date = new Date(); } | ||
file.moddate = utils.convertDate(file.date); | ||
file.offset = self.fileptr; | ||
var buf = new Buffer(1024); | ||
var len; | ||
var fileHeaderBuffer = fileHeader.create(file); | ||
buf.writeUInt32LE(0x04034b50, 0); // local file header signature | ||
buf.writeUInt16LE(file.version, 4); // version needed to extract | ||
buf.writeUInt16LE(file.bitflag, 6); // general purpose bit flag | ||
buf.writeUInt16LE(file.method, 8); // compression method | ||
buf.writeUInt32LE(file.moddate, 10); // last mod file date and time | ||
buf.writeInt32LE(0, 14); // crc32 | ||
buf.writeUInt32LE(0, 18); // compressed size | ||
buf.writeUInt32LE(0, 22); // uncompressed size | ||
buf.writeUInt16LE(0, 28); // extra field length | ||
len = buf.write(file.name, 30); // file name | ||
buf.writeUInt16LE(len, 26); // file name length | ||
len += 30; | ||
self.queue.push(buf.slice(0, len)); | ||
self.fileptr += len; | ||
self.queue.push(fileHeaderBuffer); | ||
self.fileptr += fileHeaderBuffer.length; | ||
}; | ||
@@ -52,10 +225,6 @@ | ||
var buf = new Buffer(16); | ||
buf.writeUInt32LE(0x08074b50, 0); // data descriptor record signature | ||
buf.writeInt32LE(file.crc32, 4); // crc-32 | ||
buf.writeUInt32LE(file.compressed, 8); // compressed size | ||
buf.writeUInt32LE(file.uncompressed, 12); // uncompressed size | ||
var dataDescriptorBuffer = dataDescriptorHeader.create(file); | ||
self.queue.push(buf); | ||
self.fileptr += buf.length; | ||
self.queue.push(dataDescriptorBuffer); | ||
self.fileptr += dataDescriptorBuffer.length; | ||
}; | ||
@@ -70,32 +239,11 @@ | ||
var len, buf; | ||
var centralDirectoryBuffer; | ||
for (var i=0; i<self.files.length; i++) { | ||
for (var i = 0; i < self.files.length; i++) { | ||
var file = self.files[i]; | ||
buf = new Buffer(1024); | ||
centralDirectoryBuffer = centralDirectoryHeader.create(file); | ||
// central directory file header | ||
buf.writeUInt32LE(0x02014b50, 0); // central file header signature | ||
buf.writeUInt16LE(file.version, 4); // TODO version made by | ||
buf.writeUInt16LE(file.version, 6); // version needed to extract | ||
buf.writeUInt16LE(file.bitflag, 8); // general purpose bit flag | ||
buf.writeUInt16LE(file.method, 10); // compression method | ||
buf.writeUInt32LE(file.moddate, 12); // last mod file time and date | ||
buf.writeInt32LE(file.crc32, 16); // crc-32 | ||
buf.writeUInt32LE(file.compressed, 20); // compressed size | ||
buf.writeUInt32LE(file.uncompressed, 24); // uncompressed size | ||
buf.writeUInt16LE(0, 30); // extra field length | ||
buf.writeUInt16LE(0, 32); // file comment length | ||
buf.writeUInt16LE(0, 34); // disk number where file starts | ||
buf.writeUInt16LE(0, 36); // internal file attributes | ||
buf.writeUInt32LE(0, 38); // external file attributes | ||
buf.writeUInt32LE(file.offset, 42); // relative offset | ||
len = buf.write(file.name, 46); // file name | ||
buf.writeUInt16LE(len, 28); // file name length | ||
len += 46; | ||
ptr = ptr + len; | ||
self.queue.push(buf.slice(0, len)); | ||
self.queue.push(centralDirectoryBuffer); | ||
ptr += centralDirectoryBuffer.length; | ||
} | ||
@@ -105,22 +253,18 @@ | ||
// end of central directory record | ||
len = 22; | ||
buf = new Buffer(len); | ||
var centralDirectoryFooterData = { | ||
directoryRecordsDisk: self.files.length, | ||
directoryRecords: self.files.length, | ||
directorySize: cdsize, | ||
directoryOffset: cdoffset, | ||
comment: self.options.comment | ||
}; | ||
buf.writeUInt32LE(0x06054b50, 0); // end of central dir signature | ||
buf.writeUInt16LE(0, 4); // number of this disk | ||
buf.writeUInt16LE(0, 6); // disk where central directory starts | ||
buf.writeUInt16LE(self.files.length, 8); // number of central directory records on this disk | ||
buf.writeUInt16LE(self.files.length, 10); // total number of central directory records | ||
buf.writeUInt32LE(cdsize, 12); // size of central directory in bytes | ||
buf.writeUInt32LE(cdoffset, 16); // offset of start of central directory, relative to start of archive | ||
buf.writeUInt16LE(0, 20); // comment length | ||
var centralDirectoryFooterBuffer = centralDirectoryFooter.create(centralDirectoryFooterData); | ||
ptr = ptr + len; | ||
self.queue.push(buf); | ||
self.queue.push(centralDirectoryFooterBuffer); | ||
ptr += centralDirectoryFooterBuffer.length; | ||
self.fileptr += ptr; | ||
}; | ||
zipArchiver.prototype.addFile = function(source, file, callback) { | ||
zipArchiver.prototype.addFile = function(source, data, callback) { | ||
var self = this; | ||
@@ -133,6 +277,20 @@ | ||
if (typeof source === 'string') { | ||
if (utils.lo.isString(source)) { | ||
source = new Buffer(source, 'utf-8'); | ||
} | ||
var file = utils.lo.defaults(data || {}, { | ||
name: null, | ||
comment: '', | ||
date: null, | ||
mode: null, | ||
store: false, | ||
lastModifiedDate: null | ||
}); | ||
if (utils.lo.isEmpty(file.name) || utils.lo.isString(file.name) === false) { | ||
self.emit('error', 'name must be a valid string value'); | ||
return; | ||
} | ||
file.name = utils.unixifyPath(file.name); | ||
@@ -144,2 +302,21 @@ | ||
if (utils.lo.isDate(file.date)) { | ||
file.date = file.date; | ||
} else if (utils.lo.isString(file.date)) { | ||
file.date = new Date(file.date); | ||
} else if (utils.lo.isNumber(file.lastModifiedDate) === false) { | ||
file.date = new Date(); | ||
} | ||
if (utils.lo.isNumber(file.lastModifiedDate) === false) { | ||
file.lastModifiedDate = utils.convertDateOctal(file.date); | ||
} | ||
file.versionMadeBy = 20; | ||
file.versionNeededToExtract = 20; | ||
file.flags = (1<<3) | (1<<11); | ||
file.compressionMethod = file.store ? 0 : 8; | ||
file.uncompressedSize = 0; | ||
file.compressedSize = 0; | ||
self.busy = true; | ||
@@ -149,5 +326,3 @@ self.file = file; | ||
var checksum = crc32.createCRC32(); | ||
file.uncompressed = 0; | ||
file.compressed = 0; | ||
var checksum = utils.crc32.createCRC32(); | ||
@@ -157,6 +332,6 @@ function onEnd() { | ||
if (file.store) { | ||
file.compressed = file.uncompressed; | ||
file.compressedSize = file.uncompressedSize; | ||
} | ||
self.fileptr += file.compressed; | ||
self.fileptr += file.compressedSize; | ||
self._pushDataDescriptor(file); | ||
@@ -171,3 +346,3 @@ | ||
checksum.update(chunk); | ||
file.uncompressed += chunk.length; | ||
file.uncompressedSize += chunk.length; | ||
} | ||
@@ -191,6 +366,6 @@ | ||
} else { | ||
var deflate = zlib.createDeflateRaw(self.options); | ||
var deflate = zlib.createDeflateRaw(self.zlib); | ||
deflate.on('data', function(chunk) { | ||
file.compressed += chunk.length; | ||
file.compressedSize += chunk.length; | ||
self.queue.push(chunk); | ||
@@ -222,10 +397,2 @@ }); | ||
zipArchiver.prototype._addFileStore = function(source, file, callback) { | ||
// placeholder | ||
}; | ||
zipArchiver.prototype._addFileDeflate = function(source, file, callback) { | ||
// placeholder | ||
}; | ||
zipArchiver.prototype.finalize = function(callback) { | ||
@@ -232,0 +399,0 @@ var self = this; |
@@ -1,20 +0,109 @@ | ||
module.exports = { | ||
convertDate: function(d) { | ||
var year = d.getFullYear(); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
if (year < 1980) { | ||
return (1<<21) | (1<<16); | ||
} | ||
var utils = module.exports = {}; | ||
return ((year-1980) << 25) | ((d.getMonth()+1) << 21) | (d.getDate() << 16) | | ||
(d.getHours() << 11) | (d.getMinutes() << 5) | (d.getSeconds() >> 1); | ||
}, | ||
utils.lo = require('lodash'); | ||
unixifyPath: function(filepath) { | ||
if (process.platform === 'win32') { | ||
return filepath.replace(/\\/g, '/'); | ||
} else { | ||
return filepath; | ||
utils.crc32 = require('./crc32'); | ||
utils.cleanBuffer = function(length) { | ||
var buffer = new Buffer(length); | ||
buffer.fill(0); | ||
return buffer; | ||
}; | ||
utils.collectStream = function(stream, callback) { | ||
var collection = []; | ||
var size = 0; | ||
stream.on('error', callback); | ||
stream.on('data', function(chunk) { | ||
collection.push(chunk); | ||
size += chunk.length; | ||
}); | ||
stream.on('end', function() { | ||
var buffer = new Buffer(size, 'utf8'); | ||
var offset = 0; | ||
collection.forEach(function(data) { | ||
data.copy(buffer, offset); | ||
offset += data.length; | ||
}); | ||
callback(null, buffer); | ||
}); | ||
}; | ||
utils.convertDateTimeDos = function(input) { | ||
var d = {}; | ||
d.year = (input >> 25) + 1980; | ||
d.month = ((input >> 21) & 0xF) - 1; | ||
d.day = (input >> 16) & 0xF; | ||
d.hour = (input >> 11) & 0xF; | ||
d.minutes = (input >> 5) & 0xF; | ||
d.seconds = (input & 0xF) * 2; | ||
return new Date(d.year, d.month, d.day, d.hour, d.minutes, d.seconds); | ||
}; | ||
utils.convertDateTimeOctal = function(input) { | ||
input = parseInt(input, 10) * 1000; | ||
return new Date(input); | ||
}; | ||
utils.dosDateTime = function(d) { | ||
d = (d instanceof Date) ? d : new Date(); | ||
var year = d.getFullYear(); | ||
if (year < 1980) { | ||
return (1<<21) | (1<<16); | ||
} | ||
return ((year-1980) << 25) | ((d.getMonth()+1) << 21) | (d.getDate() << 16) | | ||
(d.getHours() << 11) | (d.getMinutes() << 5) | (d.getSeconds() >> 1); | ||
}; | ||
utils.octalDateTime = function(d) { | ||
d = (d instanceof Date) ? d : new Date(); | ||
return Math.round(d / 1000).toString(8); | ||
}; | ||
utils.padNumber = function(num, bytes, base) { | ||
num = num.toString(base || 8); | ||
return this.repeat('0', bytes - num.length) + num; | ||
}; | ||
utils.repeat = function(pattern, count) { | ||
if (count < 1) { | ||
return ''; | ||
} | ||
var result = ''; | ||
while (count > 0) { | ||
if (count & 1) { | ||
result += pattern; | ||
} | ||
count >>= 1, pattern += pattern; | ||
} | ||
return result; | ||
}; | ||
utils.unixifyPath = function(filepath) { | ||
if (process.platform === 'win32') { | ||
return filepath.replace(/\\/g, '/'); | ||
} else { | ||
return filepath; | ||
} | ||
}; |
{ | ||
"name": "archiver", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "Creates Archives (ZIP) via Node Streams.", | ||
"homepage": "https://github.com/ctalkington/node-archiver", | ||
@@ -11,3 +10,2 @@ "author": { | ||
}, | ||
"repository": { | ||
@@ -17,7 +15,5 @@ "type": "git", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/ctalkington/node-archiver/issues" | ||
}, | ||
"licenses": [ | ||
@@ -29,3 +25,2 @@ { | ||
], | ||
"main": "lib/archiver.js", | ||
@@ -38,10 +33,16 @@ "engines": { | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"lodash": "~0.10.0", | ||
"rimraf": "~2.0.2", | ||
"mkdirp": "~0.3.4" | ||
}, | ||
"devDependencies": { | ||
"nodeunit": "~0.7.4" | ||
}, | ||
"keywords": ["archive", "archiver", "zip"] | ||
"keywords": [ | ||
"archive", | ||
"archiver", | ||
"zip", | ||
"tar" | ||
] | ||
} |
# Archiver [![Build Status](https://secure.travis-ci.org/ctalkington/node-archiver.png?branch=master)](http://travis-ci.org/ctalkington/node-archiver) | ||
Creates Archives (ZIP) via Node Streams. Depends on Node's build-in zlib module for compression available since version 0.6.3. | ||
Creates Archives (ZIP, TAR) via Node Streams. Depends on Node's build-in zlib module for compression available since version 0.6.3. | ||
@@ -8,39 +8,87 @@ ## Install | ||
```bash | ||
npm install archiver | ||
npm install archiver --save | ||
``` | ||
You can also use `npm install archiver@devel` to test upcoming versions. | ||
You can also use `npm install https://github.com/ctalkington/node-archiver/archive/master.tar.gz` to test upcoming versions. | ||
## API | ||
#### addFile(inputStream, data, callback) | ||
Adds a file to the Archiver stream. | ||
#### finalize(callback(written)) | ||
Finalizes the Archiver stream. When everything is done, callback is called with the total number of bytes in the archive. | ||
## Zip | ||
### Methods | ||
#### createZip(options) | ||
Creates an Archiver ZIP object. Options are passed to zlib. | ||
Creates an Archiver ZIP object. | ||
#### archive.addFile(inputStream, options, callback) | ||
### Options | ||
Adds a file to the Archiver stream. At this moment, options must contain `name`. If the `store` option is set to true, the file will be added uncompressed. | ||
#### comment `string` | ||
#### archive.finalize(callback(written)) | ||
Sets zip comment. | ||
Finalizes the Archiver stream. When everything is done, callback is called with the total number of bytes in the archive. | ||
#### zlib `object` | ||
## Example | ||
```javascript | ||
var fs = require('fs'); | ||
Passed to node's [zlib](http://nodejs.org/api/zlib.html#zlib_options) module to control compression. Options may vary by node version. | ||
var archiver = require('archiver'); | ||
### File Data | ||
var out = fs.createWriteStream('out.zip'); | ||
var zip = archiver.createZip({ level: 1 }); | ||
#### name `string` `required` | ||
zip.pipe(out); | ||
Sets file name. | ||
zip.addFile(fs.createReadStream('file1.js'), { name: 'file1.js' }, function() { | ||
zip.addFile(fs.createReadStream('file2.js'), { name: 'file2.js' }, function() { | ||
zip.finalize(function(written) { console.log(written + ' total bytes written'); }); | ||
}); | ||
}); | ||
``` | ||
#### date `string` | ||
Sets file date. | ||
#### store `boolean` | ||
If true, zip contents will be stored without compression. | ||
#### comment `string` | ||
Sets file comment. | ||
## Tar (beta) | ||
### Methods | ||
#### createTar(options) | ||
Creates an Archiver Tar object. *in testing* | ||
### Options | ||
#### recordsPerBlock `number` | ||
Sets number of records in a block, default is 20 (for advanced users only). | ||
### File Data | ||
#### name `string` `required` | ||
Sets file name. | ||
#### date `string` | ||
Sets file date. | ||
## Examples | ||
Here are a few examples to get you started. | ||
* [basic packing](https://github.com/ctalkington/node-archiver/blob/master/examples/pack.js) | ||
* [basic packing with async module](https://github.com/ctalkington/node-archiver/blob/master/examples/pack-async.js) | ||
* [tar packing wtih gzip](https://github.com/ctalkington/node-archiver/blob/master/examples/pack-tar-gzip.js) | ||
Take a peek at the [examples](https://github.com/ctalkington/node-archiver/blob/master/example) folder for a complete listing. | ||
## Contributing | ||
@@ -47,0 +95,0 @@ |
var crypto = require('crypto'); | ||
var fs = require('fs'); | ||
var mkdir = require('mkdirp'); | ||
var rimraf = require('rimraf'); | ||
var archiver = require('../lib/archiver'); | ||
var fileOutput = false; | ||
if (fileOutput) { | ||
rimraf.sync('tmp'); | ||
mkdir.sync('tmp'); | ||
} | ||
module.exports = { | ||
buffer: function(test) { | ||
tarBuffer: function(test) { | ||
test.expect(1); | ||
var actual; | ||
var expected = 'fc9f19920f1ac82fca15f6b5d9f4d0bba4d4341f'; | ||
var tar = archiver.createTar(); | ||
var hash = crypto.createHash('sha1'); | ||
var zip = archiver.createZip({level: 1}); | ||
var archive = archiver.createTar(); | ||
// create a buffer and fill it | ||
var buf = new Buffer(20000); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/buffer.tar'); | ||
archive.pipe(out); | ||
} | ||
var buffer = new Buffer(20000); | ||
for (var i = 0; i < 20000; i++) { | ||
buf.writeUInt8(i&255, i); | ||
buffer.writeUInt8(i&255, i); | ||
} | ||
zip.addFile(buf, {name: 'buffer.out', date: new Date('April 13, 2011 CET')}, function() { | ||
zip.finalize(); | ||
archive.addFile(buffer, {name: 'buffer.txt', mtime: 1354279637}, function() { | ||
archive.finalize(); | ||
}); | ||
zip.on('data', function(data) { | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
zip.on('end', function() { | ||
var digest = hash.digest('hex'); | ||
test.equals(digest, '5641d2b95f2cadaabcc22a7d646bfd41036c347d', 'data hex values should match.'); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
@@ -34,29 +58,187 @@ }); | ||
store: function(test) { | ||
tarString: function(test) { | ||
var actual; | ||
var expected = 'cce858ca0ed86f5ef3ca0fe790ac105551a54a8a'; | ||
var tar = archiver.createTar(); | ||
var hash = crypto.createHash('sha1'); | ||
var archive = archiver.createTar(); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/string.tar'); | ||
archive.pipe(out); | ||
} | ||
archive.addFile('string', {name: 'string.txt', mtime: 1354279637}, function() { | ||
archive.finalize(); | ||
}); | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
}); | ||
}, | ||
zipBuffer: function(test) { | ||
test.expect(1); | ||
var actual; | ||
var expected = 'e1f3b7b48a488f0aea0e1774a9a0dac7d5d3a642'; | ||
var hash = crypto.createHash('sha1'); | ||
var zip = archiver.createZip({level: 1}); | ||
var archive = archiver.createZip({level: 1}); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/buffer.zip'); | ||
archive.pipe(out); | ||
} | ||
var buffer = new Buffer(20000); | ||
for (var i = 0; i < 20000; i++) { | ||
buffer.writeUInt8(i&255, i); | ||
} | ||
archive.addFile(buffer, {name: 'buffer.txt', lastModifiedDate: 1049430016}, function() { | ||
archive.finalize(); | ||
}); | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
}); | ||
}, | ||
zipComments: function(test) { | ||
test.expect(1); | ||
var actual; | ||
var expected = '738f94eb1174fee0ee7b8eed2b13178f646600f0'; | ||
var hash = crypto.createHash('sha1'); | ||
var archive = archiver.createZip({ | ||
comment: 'this is a zip comment' | ||
}); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/comments.zip'); | ||
archive.pipe(out); | ||
} | ||
var buffer = new Buffer(20000); | ||
for (var i = 0; i < 20000; i++) { | ||
buffer.writeUInt8(i&255, i); | ||
} | ||
archive.addFile(buffer, {name: 'buffer.txt', lastModifiedDate: 1049430016, comment: 'this is a file comment'}, function() { | ||
archive.finalize(); | ||
}); | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
}); | ||
}, | ||
zipStore: function(test) { | ||
test.expect(1); | ||
var actual; | ||
var expected = '1ea58034c99816b8028d42a4d49eb4f626335462'; | ||
var hash = crypto.createHash('sha1'); | ||
var archive = archiver.createZip(); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/store.zip'); | ||
archive.pipe(out); | ||
} | ||
// create a buffer and fill it | ||
var buf = new Buffer(20000); | ||
var buffer = new Buffer(20000); | ||
for (var i = 0; i < 20000; i++) { | ||
buf.writeUInt8(i&255, i); | ||
buffer.writeUInt8(i&255, i); | ||
} | ||
zip.addFile(buf, {name: 'buffer.out', date: new Date('April 13, 2011 CET'), store: true}, function() { | ||
zip.finalize(); | ||
archive.addFile(buffer, {name: 'buffer.txt', lastModifiedDate: 1049430016, store: true}, function() { | ||
archive.finalize(); | ||
}); | ||
zip.on('data', function(data) { | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
zip.on('end', function() { | ||
var digest = hash.digest('hex'); | ||
test.equals(digest, 'a777c51ca558e9a2ff36f1f9b7fc70b95560df28', 'data hex values should match.'); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
}); | ||
}, | ||
zipString: function(test) { | ||
test.expect(1); | ||
var actual; | ||
var expected = 'c639c2cf6e664dc00c06cb2ebb70ed2e38521946'; | ||
var hash = crypto.createHash('sha1'); | ||
var archive = archiver.createZip({level: 1}); | ||
if (fileOutput) { | ||
var out = fs.createWriteStream('tmp/string.zip'); | ||
archive.pipe(out); | ||
} | ||
archive.addFile('string', {name: 'string.txt', lastModifiedDate: 1049430016}, function() { | ||
archive.finalize(); | ||
}); | ||
archive.on('error', function(err) { | ||
throw err; | ||
}); | ||
archive.on('data', function(data) { | ||
hash.update(data); | ||
}); | ||
archive.on('end', function() { | ||
actual = hash.digest('hex'); | ||
test.equals(actual, expected, 'data hex values should match.'); | ||
test.done(); | ||
}); | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
38316
17
939
102
3
5
+ Addedlodash@~0.10.0
+ Addedmkdirp@~0.3.4
+ Addedrimraf@~2.0.2
+ Addedgraceful-fs@1.1.14(transitive)
+ Addedlodash@0.10.0(transitive)
+ Addedmkdirp@0.3.5(transitive)
+ Addedrimraf@2.0.3(transitive)