简体   繁体   English

在PHP中创建大型zip存档

[英]Create big zip archive in PHP

In a current PHP project, I need to bundle up a bunch of PDF files in some sort of archive so the user can download them all together. 在当前的PHP项目中,我需要将一堆PDF文件打包成某种存档,以便用户可以将它们全部下载在一起。 Because zip is most common and even the most basic non-IT-Windows guys know about it, I was going for a zip archive. 因为zip是最常见的,甚至是最基本的非IT Windows人士都知道它,所以我打算准备一个zip存档。

My code looks like the following 我的代码如下所示

$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;

This script works fine if the server has enough memory. 如果服务器有足够的内存,此脚本可以正常工作。 Unfortunately our productive system is very limited so the script only works with a few PDF files, but most of the time it runs out of memory and aborts. 不幸的是,我们的生产系统非常有限,因此该脚本仅适用于几个PDF文件,但是大多数情况下它会耗尽内存并中止运行。 Adding unlink($pdf) at the end of the foreach loop didn't help, so my guess is the ZipArchive object is using up the memory. 在foreach循环的末尾添加unlink($ pdf)并没有帮助,所以我猜测ZipArchive对象正在消耗内存。

I am trying to add as little dependencies as possible to the project, so I would love to be able to solve this with PHPs (PHP 5.4) own functions or functions from Zend Framework 2. I was looking for some way of directly streaming the archive (the zip:// stream wrapper looked good at first, but it's read-only), but that seems to be impossible with zip archives. 我正在尝试向项目中添加尽可能少的依赖项,所以我希望能够使用PHP(PHP 5.4)自己的函数或Zend Framework 2中的函数解决此问题。 (zip://流包装器起初看起来不错,但它是只读的),但是对于zip档案,这似乎是不可能的。

Does anyone have an idea? 有人有主意吗? Maybe a different but also widely known type of archive that allows streaming? 也许是允许流播的另一种但也广为人知的存档类型? Compression is not a must 压缩不是必须的

I had to find a quick solution to this problem, so despite trying to avoid it, I had to use an external dependency. 我必须找到一个快速解决此问题的方法,因此尽管设法避免它,但我不得不使用外部依赖项。

I found the ZipStream class from the PHPZip project ( https://github.com/Grandt/PHPZip ) which does the job just fine. 我从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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM