只需寻找在任何操作系统上下载和解压缩Node.js中.zip
或.tar.gz
个文件的简单解决方案。
不确定这是内置还是我必须使用单独的库。有任何想法吗?只需要几行代码,所以当下一个zip文件出现在我想要在节点中下载时,它就没那么明白了。感觉这应该很容易和/或内置,但我找不到任何东西。谢谢!
答案 0 :(得分:45)
2017年(确切地说是10月26日)。
对于一种古老而普遍的技术,例如解压缩,我希望存在一个相当流行的,成熟的node.js解压缩库,这是一个停滞不前的"并且"没有维护"因为它是完整的"。
然而,大多数图书馆看起来要么是完全可怕的,要么就像几个月前一样提交。这非常令人担忧......所以我已经浏览了几个解压缩库,阅读了他们的文档,并尝试了他们的例子来试图找出WTF。例如,我尝试过这些:
yauzl
node-stream-zip
node-unzipper
node-unzip
jszip
zip
yauzl
适用于完全下载的文件。不如流媒体好。
记录良好。效果很好。有道理。
node-stream-zip
antelle' s node-stream-zip
似乎是最好的
安装:
npm install --save node-stream-zip
用法:
'use strict';
var StreamZip = require('node-stream-zip');
var zip = new StreamZip({
file: './example.zip'
, storeEntries: true
});
zip.on('error', function (err) { console.error('[ERROR]', err); });
zip.on('ready', function () {
console.log('All entries read: ' + zip.entriesCount);
//console.log(zip.entries());
});
zip.on('entry', function (entry) {
var pathname = path.resolve('./temp', entry.name);
if (/\.\./.test(path.relative('./temp', pathname))) {
console.warn("[zip warn]: ignoring maliciously crafted paths in zip file:", entry.name);
return;
}
if ('/' === entry.name[entry.name.length - 1]) {
console.log('[DIR]', entry.name);
return;
}
console.log('[FILE]', entry.name);
zip.stream(entry.name, function (err, stream) {
if (err) { console.error('Error:', err.toString()); return; }
stream.on('error', function (err) { console.log('[ERROR]', err); return; });
// example: print contents to screen
//stream.pipe(process.stdout);
// example: save contents to file
mkdirp(path.dirname(pathname, function (err) {
stream.pipe(fs.createWriteStream(pathname));
});
});
});
安全警告:
不确定这是否会entry.name
检查可能无法正确解析的恶意制作路径(例如../../../foo
或/etc/passwd
)。
您可以通过比较/\.\./.test(path.relative('./to/dir', path.resolve('./to/dir', entry.name)))
。
优点 :(为什么我认为它最好?)
<强>缺点强>:
zip.extract()
似乎无法运作(因此我在我的示例中使用了zip.stream()
)安装:
npm install --save unzipper
用法:
'use strict';
var fs = require('fs');
var unzipper = require('unzipper');
fs.createReadStream('./example.zip')
.pipe(unzipper.Parse())
.on('entry', function (entry) {
var fileName = entry.path;
var type = entry.type; // 'Directory' or 'File'
console.log();
if (/\/$/.test(fileName)) {
console.log('[DIR]', fileName, type);
return;
}
console.log('[FILE]', fileName, type);
// TODO: probably also needs the security check
entry.pipe(process.stdout/*fs.createWriteStream('output/path')*/);
// NOTE: To ignore use entry.autodrain() instead of entry.pipe()
});
<强>赞成强>:
node-stream-zip
类似的方式工作,但控制力较弱unzip
<强>缺点强>:
答案 1 :(得分:29)
结帐adm-zip。
ADM-ZIP是一个纯粹的JavaScript实现,用于NodeJS的zip数据压缩。
图书馆允许您:
- 将zip文件直接解压缩到磁盘或内存缓冲区
- 压缩文件并以
将它们存储到磁盘.zip
格式或压缩缓冲区- 更新现有
的内容/添加新/删除文件.zip
答案 2 :(得分:28)
Node通过zlib module:
内置了对gzip和deflate的支持var zlib = require('zlib');
zlib.gunzip(gzipBuffer, function(err, result) {
if(err) return console.error(err);
console.log(result);
});
修改:您甚至可以通过以下方式直接pipe
数据Gunzip
(使用request):
var request = require('request'),
zlib = require('zlib'),
fs = require('fs'),
out = fs.createWriteStream('out');
// Fetch http://example.com/foo.gz, gunzip it and store the results in 'out'
request('http://example.com/foo.gz').pipe(zlib.createGunzip()).pipe(out);
对于tar档案,有一个isaacs'tar module,由npm使用。
编辑2 :zlib
不支持zip
格式,更新了答案。这仅适用于gzip
。
答案 3 :(得分:13)
yauzl是一个强大的解压缩库。设计原则:
目前有97%的测试覆盖率。
答案 4 :(得分:10)
我尝试了一些nodejs解压缩库,包括adm-zip和unzip,然后选择了extract-zip,它是yauzl的包装器。似乎最简单的实施。
https://www.npmjs.com/package/extract-zip
var extract = require('extract-zip')
extract(zipfile, { dir: outputPath }, function (err) {
// handle err
})
答案 5 :(得分:3)
我很期待这一点,并没有找到简单的工作示例,但基于这些答案,我创建了downloadAndUnzip()
函数。
用法非常简单:
downloadAndUnzip('http://your-domain.com/archive.zip', 'yourfile.xml')
.then(function (data) {
console.log(data); // unzipped content of yourfile.xml in root of archive.zip
})
.catch(function (err) {
console.error(err);
});
这是宣言:
var AdmZip = require('adm-zip');
var request = require('request');
var downloadAndUnzip = function (url, fileName) {
/**
* Download a file
*
* @param url
*/
var download = function (url) {
return new Promise(function (resolve, reject) {
request({
url: url,
method: 'GET',
encoding: null
}, function (err, response, body) {
if (err) {
return reject(err);
}
resolve(body);
});
});
};
/**
* Unzip a Buffer
*
* @param buffer
* @returns {Promise}
*/
var unzip = function (buffer) {
return new Promise(function (resolve, reject) {
var resolved = false;
var zip = new AdmZip(buffer);
var zipEntries = zip.getEntries(); // an array of ZipEntry records
zipEntries.forEach(function (zipEntry) {
if (zipEntry.entryName == fileName) {
resolved = true;
resolve(zipEntry.getData().toString('utf8'));
}
});
if (!resolved) {
reject(new Error('No file found in archive: ' + fileName));
}
});
};
return download(url)
.then(unzip);
};
答案 6 :(得分:2)
我发现以下成功,与.zip一起使用 (这里简化发布:没有错误检查,只是将所有文件解压缩到当前文件夹)
function DownloadAndUnzip(URL){
var unzip = require('unzip');
var http = require('http');
var request = http.get(URL, function(response) {
response.pipe(unzip.Extract({path:'./'}))
});
}
答案 7 :(得分:0)
另一个工作示例:
var zlib = require('zlib');
var tar = require('tar');
var ftp = require('ftp');
var files = [];
var conn = new ftp();
conn.on('connect', function(e)
{
conn.auth(function(e)
{
if (e)
{
throw e;
}
conn.get('/tz/tzdata-latest.tar.gz', function(e, stream)
{
stream.on('success', function()
{
conn.end();
console.log("Processing files ...");
for (var name in files)
{
var file = files[name];
console.log("filename: " + name);
console.log(file);
}
console.log("OK")
});
stream.on('error', function(e)
{
console.log('ERROR during get(): ' + e);
conn.end();
});
console.log("Reading ...");
stream
.pipe(zlib.createGunzip())
.pipe(tar.Parse())
.on("entry", function (e)
{
var filename = e.props["path"];
console.log("filename:" + filename);
if( files[filename] == null )
{
files[filename] = "";
}
e.on("data", function (c)
{
files[filename] += c.toString();
})
});
});
});
})
.connect(21, "ftp.iana.org");
答案 8 :(得分:0)
import gunzip from 'gunzip-file';
const unzipAll = async () => {
try {
const compFiles = fs.readdirSync('tmp')
await Promise.all(compFiles.map( async file => {
if(file.endsWith(".gz")){
gunzip(`tmp/${file}`, `tmp/${file.slice(0, -3)}`)
}
}));
}
catch(err) {
console.log(err)
}
}
答案 9 :(得分:0)
如果您不需要将多个文件归档,而是压缩一个文件或仅压缩一个字符串内容,则可以使用 zlib.deflateRaw
/zlib.inflateRaw
。
这是一个如何在 macOS/iOS 上压缩内存字符串并在 NodeJS 中解压的示例。
// Swift, macOS/iOS
let data = "HelloZip!".data(using: .utf8)!
let compressedData = (data as NSData).compressed(using: .zlib) as Data
let compressedDataAsBase64EncodedString = compressedData.base64EncodedString()
print(compressedDataAsBase64EncodedString)
// Prints: 80jNycmPyixQBAA=
// JS, AWS Lambda.
import zlib from "zlib";
const compressedDataAsBase64EncodedString = "80jNycmPyixQBAA="
const compressedData = Buffer.from(compressedDataAsBase64EncodedString, "base64")
const data = zlib.inflateRawSync(compressedData)
console.log(data.toString())
// Prints: HelloZip!
答案 10 :(得分:-1)
下载并解压缩.tar.gz
:
const https = require("https");
const tar = require("tar");
https.get("https://url.to/your.tar.gz", function(response) {
response.pipe(
tar.x({
strip: 1,
C: "some-dir"
})
);
});
答案 11 :(得分:-2)
您也可以使用“解压缩”简单地提取现有的zip文件。它适用于任何大小的文件,您需要将其添加为npm的依赖项。
fs.createReadStream(filePath).pipe(unzip.Extract({path:moveIntoFolder})).on('close', function(){
//To do after unzip
callback();
});