Node.js:使用zlib + tar指定要解压缩的文件

12

安装过程会下载一个 .tar.gz 压缩文件,然后将文件提取到目标目录。然而,并非所有压缩文件中的文件都是必需的,我想指定应该提取哪些文件。一种幼稚的方法是在提取后删除不必要的文件,但我想有一种更“干净”的方式并进行筛选。

这是否可行?

到目前为止,我拥有的(相关)代码如下(已精简以提高可读性)

var fs = require('fs');
var tar = require('tar');
var zlib = require('zlib');

var log = console.log;

var tarball = 'path/to/downloaded/archive.tar.gz';
var dest = 'path/to/destination';

fs.createReadStream(tarball)
  .on("error", log)
  .pipe(zlib.Unzip())
  .pipe(tar.Extract({ path: dest }))
  .on("end", log);

谢谢。

2个回答

14

它的工作方式类似于 unzip 模块:

var fs = require('fs');
var tar = require('tar');
var zlib = require('zlib');
var path = require('path');
var mkdirp = require('mkdirp'); // used to create directory tree

var log = console.log;

var tarball = 'path/to/downloaded/archive.tar.gz';
var dest    = 'path/to/destination';

fs.createReadStream(tarball)
  .on('error', log)
  .pipe(zlib.Unzip())
  .pipe(tar.Parse())
  .on('entry', function(entry) {
    if (/\.js$/.test(entry.path)) { // only extract JS files, for instance
      var isDir     = 'Directory' === entry.type;
      var fullpath  = path.join(dest, entry.path);
      var directory = isDir ? fullpath : path.dirname(fullpath);

      mkdirp(directory, function(err) {
        if (err) throw err;
        if (! isDir) { // should really make this an `if (isFile)` check...
          entry.pipe(fs.createWriteStream(fullpath));
        }
      });
    }
  });

@rynop 很好的发现,不过在调用 mkdirp() 之前我会执行那个检查。 - robertklep
笑死了,没问题了。另外我发现在解压缩.tar.gz文件时,其中的文件会在磁盘上损坏。你以前见过这种情况吗?虽然文件已按正确的名称和结构放置在磁盘上,但文件内部的jar包却是损坏的。如果不使用“仅提取JS文件”行并改用tar.Extract()命令,则不会出现此问题。 - rynop
@rynop 我曾经使用过类似的代码来提取tar文件,而且它一直都很有效。如果你有一个样本tar文件给我,我很乐意看一下。 - robertklep
@robertklep,非常感谢您的帮助:http://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_2015-01-27.tar.gz。您可以在https://github.com/doapp-ryanp/dynamodb-local/blob/master/index.js#L105看到我的代码正在运行-如果我改为`tar.Parse()`并使用您的逻辑,则二进制文件会损坏(大小不同)。 - rynop
@rynop,这对我来说似乎完全没问题:https://gist.github.com/robertklep/01dd2c64a0fe9f5483d5(请随意在那里留下评论,而不是在这里 :-)) - robertklep
如果 rynop 在 Windows 上,而 robertklep 在类 Unix 系统上,则对于损坏的文件,此参数适用。必须对文件路径进行规范化处理。\ 表示 Windows,/ 表示类 Unix。 - bigkahunaburger

0

你可以查看这篇文章找到一个好的解决方案。

顺便说一下,在zlib文档中,你会看到可以通过调用.unzip()来指定“缓冲区”。


不,存档可能非常大,我不想分配那么多RAM。内存占用必须最小化。此外,存档包含一个目录结构,你提出的方法不适用。 - Yanick Rochon
我必须读取tar文件中提取的文件。我应该何时调用我的读取函数?我尝试使用onClose,但在那之前我的文件尚未完全写入。您可以看到我的代码。 - Rajeev Raina
fs.createReadStream(filename) .pipe(zlib.Unzip()) .pipe(new tar.Parse()) .on('entry', function(entry) { { var isDir = 'Directory' === entry.type; var fullpath = path.join(dest, entry.path); var directory = isDir ? fullpath : path.dirname(fullpath); mkdirp(directory, function(err) { if (err) throw err; if (! isDir) { entry.pipe(fs.createWriteStream(fullpath) .on('error', function(e){alert('Error');}) ); }});} }).on('close', function(){setTimeout(readXMLFile(sysObject.path + '\layout_new.xml'),0);}) - Rajeev Raina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接