Open eempey opened 8 years ago
I used php://output
as such. Not sure if this will help solve your issue. Good luck.
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$phpWord->getCompatibility()->setOoxmlVersion(15);
$section = $phpWord->addSection();
$section->addText( htmlspecialchars( 'Hello World!' ) );
//Headers
$headers = [
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename="' . $client->last_name . '.docx"',
'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'Content-Transfer-Encoding' => 'binary',
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Expires' => '0',
];
//Writer
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter( $phpWord, 'Word2007' );
//Start read from output buffer
ob_start();
//Save to output
$objWriter->save( 'php://output' );
//Get the file contents from output buffer and clean
$file = ob_get_clean();
return response()->make( $file, 200, $headers );
Also when using version 0.12.*
you have to make sure to use htmlspecialchars for all string values that may have html special characters e.g. htmlspecialchars( $value )
.
I get this issue as well, but using nginx so it's not an IIS-specific thing. I'll try @ericdowell's suggestions and see if that fixes the issue for me.
@jaymiethomas can you share the corrupt document so we can check the content?
Thanks, @troosan - I've attached a sample document. Office 2016 (which the customer uses) is saying there is corrupt data in the file.
report - Sample Coal Project.docx
Here's the Laravel controller code which is generating this, in its entirety:
$header = array('size' => 12, 'bold' => true);
$columnHeader = array('size' => 9, 'bold' => true);
$cellContent = array('size' => 9);
$footnoteHeader = array('size' => 8, 'bold' => true);
$footnoteText = array('size' => 8);
$section = $phpWord->addSection();
$section->addTextBreak(2);
$section->addText('Background', $header);
$section->addTextBreak(1);
$section->addTextBreak(1);
$section->addTextBreak(2);
$section->addText('Performance', $header);
$section->addTextBreak(1);
$section->addText('The data below demonstrates the performance of the ' . $project->name . ' project by ' . $project->company->name . '. The data has also been benchmarked against internal and aggregated industry data for other projects in the ' . $project->sector->name . ' sector.');
$section->addTextBreak(2);
$rows = 1;
$cols = 7;
$table = $section->addTable();
$table->addRow();
$table->addCell(4000)->addText("Name", $columnHeader);
$table->addCell(2500)->addText("Sector", $columnHeader);
$table->addCell(2000)->addText("Size", $columnHeader);
$table->addCell(2300)->addText("Cost", $columnHeader);
$table->addCell(2000)->addText("Total Waste", $columnHeader);
$table->addCell(2000)->addText("Per 100m2", $columnHeader);
$table->addCell(2000)->addText("Per £100k", $columnHeader);
$table->addRow();
$table->addCell(4000)->addText($project->name, $cellContent);
$table->addCell(2500)->addText($project->sector->name, $cellContent);
$table->addCell(2000)->addText($project->present()->size, $cellContent);
$table->addCell(2300)->addText($project->present()->cost, $cellContent);
$totalWaste = $this->viewHelper->totalWaste($project, $project->wasteRecords->where('record_type', 1));
$table->addCell(2000)->addText($totalWaste, $cellContent);
$table->addCell(2000)->addText(number_format($this->viewHelper->calculatePer100m2($totalWaste, $project->size) * 100, 2), $cellContent);
$table->addCell(2000)->addText(number_format($this->viewHelper->calculatePer100k($totalWaste, $project->cost) * 100, 2), $cellContent);
$section->addTextBreak(2);
$section->addText('Performance against other ' . $project->sector->name . ' projects', $header);
$section->addTextBreak(1);
$table = $section->addTable();
$table->addRow();
$table->addCell(5000)->addText("Source", $columnHeader);
$table->addCell(2500)->addText("m3 Per 100m2", $columnHeader);
$table->addCell(2500)->addText("m3 Per £100k", $columnHeader);
$table->addRow();
$table->addCell(5000)->addText($project->company->name . " project averages", $cellContent);
$table->addCell(2500)->addText(number_format($companyBenchmarkResults->per100m2, 2), $cellContent);
$table->addCell(2500)->addText(number_format($companyBenchmarkResults->per100k, 2), $cellContent);
$table->addRow();
$table->addCell(5000)->addText("Aggregated industry project averages", $cellContent);
$table->addCell(2500)->addText(number_format($industryBenchmarkResults->per100m2, 2), $cellContent);
$table->addCell(2500)->addText(number_format($industryBenchmarkResults->per100k, 2), $cellContent);
$section->addTextBreak(2);
$section->addText('Please note', $footnoteHeader);
$section->addText('This information has been provided for information purposes only. Whilst we try to ensure that the content is accurate, we cannot be held responsible for any errors or omissions therein, nor for the consequences of these.', $footnoteText);
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
try {
$objWriter->save(storage_path('report - ' . $project->name . '.docx'));
} catch (Exception $e) {
}
return response()->download(storage_path('report - ' . $project->name . '.docx'));```
Have you tried this with the latest PHPWord version? I tried locally and it works fine.
I was on v0.13 and just upgraded to v0.14, but I still see the same issue with corrupted file contents. Were you able to open my sample document, @troosan? Also, what are you using to open the documents? I'm using Word 2016 MSO (16.0.8201.2213)
.
indeed, I cannot open the document, tried with word 2016 (mac) and word 2010 (win), same result. I could only open it with libreoffice
Thanks @troosan. But when you run the code I supplied are you able to open in Word the document that the code generates?
yes, but I had to hard code some values of course. Can you generate a valid document? If not, it's maybe linked to the values inside $project?
Thanks, that's a great clue - I'll check it out. It might be that I need to call htmlspecialchars()
on the $project
contents.
I've commented-out all the document content code and have been incrementally commenting it back in to identify the line which breaks the document. Curiously, it's adding the row immediately after adding the table element:
$table = $section->addTable();
$table->addRow();
There's no dynamic content here, but it's that which appears to break the document - I can't think why that would be the case?
An update on this: I think I've solved it. The present()->size
line was returning <sup>
tags which I think was causing the issue. I did have once instance of only using addRow()
which caused the document to be unreadable, but I've been unable to produce that.
For anyone reading this in future, check that you're not passing HTML entities into your Word document unencoded. That's currently my best guess as to what's gone wrong here.
I have PHP office integrated in a laravel application. It works when I run it on my xampp localhost, but when I use it on the IIS production server I get "We're sorry, we can't open text.docx because we found a problem with its contents. The file is corrupt and cannot be opened." I can click through two more error pop-ups warning me about "unreadable content" and then open the file. The file looks fine when I do finally get it opened. The IIS server uses php version 5.6.14, libxml2 Version 2.9.2 with xml reader & writer enabled and Zend Extension 220131226. Here is the offending code, I pulled the sections out and still the same error so I know it's not my string formatting. Also possibly relevant is that on both servers the document opens in "Read Mode" instead of "Print Layout". I would prefer it open in Print Layout.