Issues

ZF-10820: PDF's created with Zend_Pdf::save($file, true) won't open in Adobe Reader

Description

We have a report that generates large PDFs (almost 1,000 pages on our largest) that we've been working on cleaning up and fixing memory issues on. One of the biggest things we can change is incrementally saving the PDF instead of collecting all of the pages in memory before saving. Unfortunately every PDF we've created with the $updateOnly flag set will not open in Adobe Reader or OSX's Preview.app. Interestingly enough the PDF viewer evince on Linux displays the file correctly.

The error message from Reader is: Adobe Reader could not open 'test.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).


<?php

set_include_path(__DIR__ . '/library');

require './library/Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();

if (is_file($file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'test.pdf')) {
    unlink($file);
}

$pdf = new Zend_Pdf();
for ($i = 0; $i < 5; $i++) {
    $page = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
    $page->setFont(Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_COURIER), 7);

    $page->drawText('Test Page ' . ($i + 1), 25, $page->getHeight() - 25);
    $pdf->pages[] = $page;
    $pdf->save($file, true);
}

?>

Comments

I have found the solution! Setting the $updateOnly flag on a brand new file does not work. I expected the library to be smart enough to realize it's a new file and operate on it as such. If this is intended behavior I believe it should be documented somewhere.

I don't know if this is considered a breaking change, but IMVHO it would make sense to check whether the target file already exists before appending to it. The write mode (ab vs. wb) does not matter, but the flag value passed to the render() method does. I have prepared a simple patch that changes the $updateOnly flag to false if the target file does not exist.

Patch for ZF-10820

Fixed.

PDF is always saved as full document (not only incremental part) if it's created using:


$pdf = new Zend_Pdf();

but if document is loaded it may be saved as incremental section for different purposes, it also allows to work with streams or other environments where file_exists() is not relevant.