使用PHP编写一个.tgz文件,其中包含100000多个条目,但避免单独写入文件


Writing a .tgz file using PHP with 100,000+ entries, but avoiding individual file writes

我正在尝试编写一个.tgz文件,该文件包含数十个甚至数十万个文件条目,每个条目的内容都来自数据库中的一个字符串。每个文件条目大约有2-5k的数据。

我想避免这样做而不必先写出文件。目前,我使用PHP创建一个传统的目录结构,编写文件,然后在最后使用shellexec从中生成一个tgz。

我们使用的磁盘速度很慢,因此写入数万个文件需要很长时间。即使在另一台使用tmpfs ramdisk和大量CPU的快速磁盘的机器上运行原型,我也能获得每秒100-200个文件条目的速度,这感觉很慢——对于目录结构中的150000个文件来说,需要半个小时。一旦编写完成,从本机操作系统目录结构到tgz的实际转换就没有问题了。

我希望用PharData来写。然而,PharData::addFromString似乎在添加文件后立即进行文件写入,而不是Open->Add->Writeout模式。

有人能在这里提出一些策略吗?

最终的tgz文件将可供下载,并且不会经常刷新。但是,由于要创建一系列这样的文件,仅打包就需要等待30-60多分钟,这就成了一个很大的障碍。

您可以直接使用php-gzopen/gzwrite/gzclose函数,并格式化您自己的tar头,然后是条目数据。php-gzwrite文档页面上有一个示例。

这是一个老问题,但我会尽力回答。
Phar缓冲至少支持PHP 5.3:

Phar::startBuffering()
开始缓冲Phar写入操作,不要修改磁盘上的Phar对象

Phar::stopBuffering()
停止缓冲对Phar档案的写入请求,并将更改保存到磁盘


一个关于它的小例子:

<?php
$phar = new Phar('bundle.phar');
$phar->startBuffering();
// ... adding files and contents ...
$phar->setStub('<?php __HALT_COMPILER();');
$phar->stopBuffering();