【问题标题】:Create .tar.gz file using PHP使用 PHP 创建 .tar.gz 文件
【发布时间】:2018-01-13 19:23:16
【问题描述】:

我正在进行的项目需要创建 .tar.gz 档案并将其提供给外部服务。此外部服务仅适用于 .tar.gz,因此另一种类型的存档是不可能的。我正在处理的代码将执行的服务器不允许访问系统调用。所以systemexec、反引号等是不行的。这意味着我必须依靠纯 PHP 实现来创建 .tar.gz 文件。

做了一些研究,似乎PharData 将有助于实现结果。但是我遇到了困难,需要一些指导。

考虑以下文件夹布局:

parent folder
  - child folder 1
  - child folder 2
  - file1
  - file2

我正在使用下面的代码 sn-p 创建 .tar.gz 存档,它可以解决问题,但最终结果存在一个小问题,它不包含父文件夹,而是其中的所有内容。

$pd = new PharData('archive.tar');

$dir = realpath("parent-folder");

$pd->buildFromDirectory($dir);

$pd->compress(Phar::GZ);

unset( $pd );

unlink('archive.tar');

创建存档时,它必须包含上述确切的文件夹布局。使用上面提到的代码 sn-p,存档包含除父文件夹之外的所有内容,父文件夹是外部服务的交易破坏者:

- child folder 1
- child folder 2
- file1
- file2

buildFromDirectory 的描述确实提到了以下内容,因此它不包含存档中的父文件夹是可以理解的:

从目录中的文件构建一个 tar/zip 存档。

我也尝试过使用buildFromIterator,但最终结果也相同,即父文件夹不包含在存档中。我能够使用addFile 获得所需的结果,但这非常缓慢

做了更多研究后,我发现了以下库:https://github.com/alchemy-fr/Zippy。但这需要composer 支持,这在服务器上不可用。如果有人可以指导我实现最终结果,我将不胜感激。我也愿意使用其他一些方法或库,只要它的纯 PHP 实现并且不需要任何外部依赖项。不确定它是否有帮助,但执行代码的服务器有 PHP 5.6

【问题讨论】:

  • 服务器上不需要作曲家。您只需要在本地开发机器上使用 composer。
  • @DanielO。感谢您提供的重要信息,不胜感激。正如您已经知道的那样,我对作曲家的经验是有限的! :) 我会试试看。

标签: php tar phar


【解决方案1】:

使用“parent-folder”的父级作为Phar::buildFromDirectory() 的基础,并使用其第二个参数将结果限制为“parent-folder”,例如:

$parent = dirname("parent-folder");
$pd->buildFromDirectory($parent, '#^'.preg_quote("$parent/parent-folder/", "#").'#');
$pd->compress(Phar::GZ);

【讨论】:

  • Paul,感谢您提供的代码 sn-p,就像一个魅力。使用buildFromIterator 是否可以实现相同的壮举?像英雄一样,我去向我的 PM 演示代码,他说“哦,但我们需要排除某些文件夹”,doh!
  • 实际上,我使用了CallbackFilterIterator,它成功了。
【解决方案2】:

我最终不得不这样做,因为这个问题是谷歌上针对该问题的第一个结果,所以这是执行此操作的最佳方法,无需使用正则表达式(如果您想从中提取一个目录,则无法很好地扩展一个包含许多其他目录的目录)。

function buildFiles($folder, $dir, $retarr = []) {
    $i = new DirectoryIterator("$folder/$dir");
    foreach ($i as $d) {
        if ($d->isDot()) {
            continue;
        }
        if ($d->isDir()) {
            $newdir = "$dir/" . basename($d->getPathname());
            $retarr = buildFiles($folder, $newdir, $retarr);
        } else {
            $dest = "$dir/" . $d->getFilename();
            $retarr[$dest] = $d->getPathname();
        }
    }
    return $retarr;
}
 
$out = "/tmp/file.tar";
$sourcedir = "/data/folder";
$subfolder = "folder2";
$p = new PharData($out);
$filemap = buildFiles($sourcedir, $subfolder);
$iterator = new ArrayIterator($filemap);
$p->buildFromIterator($iterator);
$p->compress(\Phar::GZ);
unlink($out); // $out.gz has been created, remove the original .tar

这允许您从 /data/folder 中选择 /data/folder/folder2,即使 /data/folder 包含数百万个 OTHER 文件夹。然后它会创建一个 tar.gz,其中的内容都以文件夹名称开头。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多