Question

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. Because zip is most common and even the most basic non-IT-Windows guys know about it, I was going for a zip archive.

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. 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.

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.

Does anyone have an idea? Maybe a different but also widely known type of archive that allows streaming? Compression is not a must

Was it helpful?

Solution

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.

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

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

$zip->finalize();
exit;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top