Description
I need to generate a pretty large Word document, with lots of data from a database.
Instead of fetching all the data in one go, and risking a timeout, I fetch a set number of elements at a time, and process the document in a batch.
A very crude simplification would look like this:
$filepath = '/absolute/path/to/file.docx';
// Initial batch run:
$phpword = new \PhpOffice\PhpWord\PhpWord();
$phpword->getSettings()->setUpdateFields(true);
// Set some settings...
$section = $phpword->addSection();
// Add text, images, etc;
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpword, 'Word2007');
$writer->save($filepath);
// Subsequent batch runs:
$phpword = \PhpOffice\PhpWord\IOFactory::load($filepath);
$phpword->getSettings()->setUpdateFields(true);
// Set some settings...
$section = $phpword->addSection();
// Add text, images, etc;
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpword, 'Word2007');
$writer->save($filepath);
So far so good.
However (and I've been banging my head for hours now), if at one point I add an image, I can no longer update the document. It will throw an exception: Could not close zip file, and PHP throws the following warning: ZipArchive::close(): Invalid or uninitialized Zip object.
If I use PeclZip, it will not throw any error, but the file won't be readable.
Expected Behavior
I would expect a document to be loaded correctly, and then be save-able again. This is the case as long as no image is added.
Current Behavior
If the document contains an image, it can be opened, but not updated.
I tried copying the file prior to opening it, renaming it, to no avail. I checked file permissions, but it doesn't seem to matter. I updated the user:group of the webserver to make certain it wasn't that either: no success.
Failure Information
\PhpOffice\PhpWord\Exception\Exception
thrown: Could not close zip file (in \PhpOffice\PhpWord\Shared\ZipArchive::close()
)
PHP warning: ZipArchive::close(): Invalid or uninitialized Zip object
How to Reproduce
Running this code triggers the error (I'm on the latest dev commit):
$filepath = '/absolute/path/to/file.docx';
$image = '/absolute/path/to/image.png';
$phpword = new \PhpOffice\PhpWord\PhpWord();
$phpword->getSettings()->setUpdateFields(true);
$phpword->setDefaultFontName('Verdana');
$phpword->setDefaultFontSize(9);
$section = $phpword->addSection();
$section->addImage($image);
$section->addTextBreak();
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpword, 'Word2007');
$writer->save($filepath);
sleep(5); // This is not needed, but just to make absolutely sure
$phpword = \PhpOffice\PhpWord\IOFactory::load($filepath);
$phpword->getSettings()->setUpdateFields(true);
$phpword->setDefaultFontName('Verdana');
$phpword->setDefaultFontSize(9);
$section = $phpword->addSection();
$section->addText('Lorem ipsum');
$section->addTextBreak();
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpword, 'Word2007');
$writer->save($filepath);
Context
- PHP version: 5.6.31 and 7.1.12
- PHPWord version: master-dev