Create big zip archive in PHP
在当前的一个PHP项目中,我需要将一堆PDF文件打包到某种归档文件中,这样用户就可以一起下载它们了。因为Zip是最常见的,甚至是最基本的非IT Windows用户都知道的,所以我要找一个Zip存档。
我的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | $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对象正在耗尽内存。
我正试图向项目中添加尽可能少的依赖项,所以我希望能够用phps(php 5.4)自己的函数或zend framework 2中的函数来解决这个问题。我在寻找直接流式传输归档文件的方法(zip://stream包装器起初看起来不错,但它是只读的),但对于zip归档文件来说,这似乎是不可能的。
有人有主意吗?可能是一种不同但又广为人知的允许流式传输的归档类型?压缩不是必须的
我必须找到一个快速解决这个问题的方法,所以尽管试图避免它,我还是不得不使用一个外部依赖。
我在phpzip项目(https://github.com/grant/phpzip)中找到了zipstream类,它可以很好地完成工作。
1 2 3 4 5 6 7 8 9 10 | $zip = new \ZipStream("invoices.zip"); foreach($invoices as $invoice) { $pdf = new InvoicePdf($invoice); $zip->addFile($pdf->render(), $pdf->getFilename()); } $zip->finalize(); exit; |