用PHP创建大型zip存档

时间:2014-03-03 14:22:24

标签: php stream zip on-the-fly

在当前的PHP项目中,我需要将一堆PDF文件捆绑在某种存档中,以便用户可以一起下载它们。因为zip是最常见的,即使是最基本的非IT-Windows人员都知道它,我还是想要一个zip存档。

我的代码如下所示

$invoices = getRequestedInvoices(); // load all requested invoices, this function is just for demonstration

// Create a temporary zip archive
$filename = tempnam("tmp", "zip");
$zip = new \ZipArchive();
$zip->open($filename, \ZipArchive::OVERWRITE);

foreach($invoices as $invoice)
{
    // create the pdf file and add it to the archive
    $pdf = new InvoicePdf($invoice); // this is derived from \ZendPdf\PdfDocument
    $zip->addFromString($pdf->getFilename(), $pdf->render()); // for clarification: the getFilename method creates a filename for the PDF based on the invoice's id
}

$zip->close();

header('Content-Type: application/zip');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename="invoices.zip"');
readfile($filename);
unlink($filename);
exit;

如果服务器有足够的内存,此脚本可以正常工作。不幸的是,我们的生产系统非常有限,因此脚本只能处理一些PDF文件,但大多数情况下它会耗尽内存和中止。在foreach循环结束时添加unlink($ pdf)没有帮助,所以我的猜测是ZipArchive对象耗尽了内存。

我试图尽可能少地为项目添加依赖项,所以我希望能够用PHP(PHP 5.4)自己的函数或Zend Framework 2中的函数来解决这个问题。我正在寻找一些直接的方法流式传输存档(zip://流式包装器起初看起来很好,但它是只读的),但这对于zip存档来说似乎是不可能的。

有没有人有想法?也许是一种不同但也广为人知的存档类型,允许流式传输?压缩不是必须的

1 个答案:

答案 0 :(得分:0)

我必须找到这个问题的快速解决方案,所以尽管试图避免它,但我不得不使用外部依赖。

我从PHPZip项目(https://github.com/Grandt/PHPZip)找到了ZipStream类,它完成了这项工作。

$zip = new \ZipStream("invoices.zip");

foreach($invoices as $invoice)
{
    $pdf = new InvoicePdf($invoice);
    $zip->addFile($pdf->render(), $pdf->getFilename());
}

$zip->finalize();
exit;