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.
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.
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.
\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_
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);
I forgot to mention that the initial exception is this one:
\PhpOffice\PhpWord\Exception\InvalidImageException: _Invalid image: zip:///absolute/path/to/file.docx#word/media/section_image1.png_ (in \PhpOffice\PhpWord\Element\Image::checkImage())
I applied the following changes, which gets a step further, but still fails to close the document (Exception described above):
diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php
index f1f6bab..68c813e 100644
--- a/src/PhpWord/Element/Image.php
+++ b/src/PhpWord/Element/Image.php
@@ -454,7 +454,7 @@ class Image extends AbstractElement
$zip = new ZipArchive();
if ($zip->open($zipFilename) !== false) {
- if ($zip->locateName($imageFilename)) {
+ if ($zip->locateName($imageFilename) !== false) {
$imageContent = $zip->getFromName($imageFilename);
if ($imageContent !== false) {
file_put_contents($tempFilename, $imageContent);
what if you add the sections inside a function block? (so that variables get undefined when the function ends)
I suspect you actually need unset() to undefine/destroy all lingering variables before they get reused.
(or you are on to a bug)
Actually, the error also happens in a batch, where a JS function requests a
page, which triggers the PHP code. So the request ends, and no variables
are kept.
It works fine with just text. It also works if the first few batch calls
only add text, then one call adds an image. The next call will then fail,
regardless if we add text or an image.
@wadmiraal could you give it a try with the dev-develop version, just to make sure this is still valid?
I just tried again with the latest dev-develop branch. Clean install in another folder, called composer install to get a fresh copy of all dependencies.
I then modified src/PhpWord/Element/Image.php again, as noted in my previous comment, as the image is at position 0, which is a "falsy" value, and breaks the loading of a Docx file.
I then created the following PHP file in the root of the PHPWord repo (test.php):
require 'vendor/autoload.php';
$filepath = 'file.docx';
$image = '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);
_Note: Make sure file.docx doesn't exist before executing the file._
I then executed it like this: php test.php.
Stack trace:
PHP Warning: ZipArchive::close(): Invalid or uninitialized Zip object in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php on line 163
PHP Stack trace:
PHP 1. {main}() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:0
PHP 2. PhpOffice\PhpWord\Writer\Word2007->save() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:28
PHP 3. PhpOffice\PhpWord\Writer\AbstractWriter->addFilesToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/Word2007.php:111
PHP 4. PhpOffice\PhpWord\Writer\AbstractWriter->addFileToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:362
PHP 5. PhpOffice\PhpWord\Shared\ZipArchive->close() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:391
PHP 6. ZipArchive->close() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php:163
Warning: ZipArchive::close(): Invalid or uninitialized Zip object in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php on line 163
Call Stack:
0.0002 364584 1. {main}() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:0
5.0326 3125784 2. PhpOffice\PhpWord\Writer\Word2007->save() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:28
5.0329 3126936 3. PhpOffice\PhpWord\Writer\AbstractWriter->addFilesToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/Word2007.php:111
5.0329 3126992 4. PhpOffice\PhpWord\Writer\AbstractWriter->addFileToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:362
5.0330 3127360 5. PhpOffice\PhpWord\Shared\ZipArchive->close() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:391
5.0330 3127360 6. ZipArchive->close() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php:163
PHP Fatal error: Uncaught PhpOffice\PhpWord\Exception\Exception: Could not close zip file file.docx. in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php:164
Stack trace:
#0 /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php(391): PhpOffice\PhpWord\Shared\ZipArchive->close()
#1 /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php(362): PhpOffice\PhpWord\Writer\AbstractWriter->addFileToPackage(Object(PhpOffice\PhpWord\Shared\ZipArchive), 'file.docx#word/...', 'word/media/sect...')
#2 /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/Word2007.php(111): PhpOffice\PhpWord\Writer\AbstractWriter->addFilesToPackage(Object(PhpOffice\PhpWord\Shared\ZipArchive), Array)
#3 /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php(28): PhpOffice\PhpWord\Writer\W in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php on line 164
Fatal error: Uncaught PhpOffice\PhpWord\Exception\Exception: Could not close zip file file.docx. in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php on line 164
PhpOffice\PhpWord\Exception\Exception: Could not close zip file file.docx. in /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Shared/ZipArchive.php on line 164
Call Stack:
0.0002 364584 1. {main}() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:0
5.0326 3125784 2. PhpOffice\PhpWord\Writer\Word2007->save() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/test.php:28
5.0329 3126936 3. PhpOffice\PhpWord\Writer\AbstractWriter->addFilesToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/Word2007.php:111
5.0329 3126992 4. PhpOffice\PhpWord\Writer\AbstractWriter->addFileToPackage() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:362
5.0330 3127360 5. PhpOffice\PhpWord\Shared\ZipArchive->close() /Users/wadmiraal/Documents/inovae/projects/wto/tprqa/sites/all/libraries/PHPWord/src/PhpWord/Writer/AbstractWriter.php:391
Experiencing same problem after adding image.
I am adding image like this:
$section->addImage($path);
And when trying to do it second time it errors out:
Invalid image: zip://F:\WEB\xampp\htdocs\workflow\storage\/app/files/FILENAME.docx#word/media/section_image1.jpg
I have the same problem any solution ? The file forget de previous images
Check the result:

Most helpful comment
Experiencing same problem after adding image.
I am adding image like this:
$section->addImage($path);
And when trying to do it second time it errors out:
Invalid image: zip://F:\WEB\xampp\htdocs\workflow\storage\/app/files/FILENAME.docx#word/media/section_image1.jpg