问题
I'm using PHPExcel to export some data to user in an excel file. I would like the script to send the excel file to the user immediately after it's creation. Here is my test code:
try{
/* Some test data */
$data = array(
array(1, 10 , 2 ,),
array(3, 'qqq', 'some string' ,),
);
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
/* Fill the excel sheet with the data */
$rowI = 0;
foreach($data as $row){
$colI = 0;
foreach($row as $v){
$colChar = PHPExcel_Cell::stringFromColumnIndex($colI++);
$cellId = $colChar.($rowI+1);
$objPHPExcel->getActiveSheet()->SetCellValue($cellId, $v);
}
$rowI++;
}
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="export.xlsx"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
}catch(Exception $e){
echo $e->__toString();
}
On my local server (Windows 7 x64, Php 5.3.8, Apache 2.2.21)
I get a valid xlsx file. There are no errors.
But there is problem on the live server (Linux 2.6.32-5-amd64, PHP 5.3.3-7+squeeze13, Apache 2.2.16)
. The script lets the browser to download the "export.xlsx" file with such content:
exception 'PHPExcel_Writer_Exception' with message 'Could not close zip file php://output.' in /var/www/someuser/data/www/somedomain.com/libs/PHPExcel/Writer/Excel2007.php:348
Stack trace:
#0 /var/www/someuser/data/www/somedomain.com/classes/Report/Leads/Export.php(339): PHPExcel_Writer_Excel2007->save('php://output')
#1 /var/www/someuser/data/www/somedomain.com/application/pages/account/controllers/TestController.php(13): Report_Leads_Export->Test()
#2 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Action.php(516): Account_TestController->indexAction()
#3 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Dispatcher/Standard.php(295): Zend_Controller_Action->dispatch('indexAction')
#4 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#5 /var/www/someuser/data/www/somedomain.com/index.php(511): Zend_Controller_Front->dispatch()
#6 {main}
PHP is NOT running in Safe Mode. The "open_basedir" option is empty (it's commented out).
I have found such code in the PHPExcel files:
if ($objZip->close() === false) {
throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename.");
}
So the reason of the problem is that $objZip->close() === false
where $objZip
is an instance of ZipArchive
class.
What is the reason of the problem and how can I solve it? Thank you.
回答1:
The most common cause of this error when saving to php://output is an open_basedir restriction that doesn't include a valid system's temp folder (e.g. /tmp
), or permissions for the system's temp folder... suhosin can also affect this, even when the obvious permissions appear to be set correctly.
A possible workround is to write the file to the filesystem in a directory that you know you do have full privileges to write, and then use readfile() to stream that file to php://output before deleting the file
回答2:
Thanks to Mark Baker. His answer has solved the problem. I have written a simple helper method using his approach.
static function SaveViaTempFile($objWriter){
$filePath = sys_get_temp_dir() . "/" . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
$objWriter->save($filePath);
readfile($filePath);
unlink($filePath);
}
And I have just replaced $objWriter->save('php://output')
with SaveViaTempFile($objWriter)
回答3:
Hi i tried the following: in a server linux Centos 7.0 do not specified the route of directory tmp, input:
function SaveViaTempFile($objWriter){
$filePath = '' . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
$objWriter->save($filePath);
readfile($filePath);
unlink($filePath);
exit;
}
and work !!
回答4:
For some people who may have this same ERROR message : it may very simply be because the filename you're trying to save to is actually already open in your Excel.. Was my case
回答5:
Excelent Friend Work for me in php 7.1.2 and work in PhpSpreadsheet, fix the same file.
PhpSpreadsheet/Writer/Excel2007.php
the solution is in de function save in Excel2007.php
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
$pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');
Replace the second line with this:
$pFilename = dirname(__FILE__).'/'. rand(0, getrandmax()) . rand(0, getrandmax()) . ".phpxltmp";
thanks.
回答6:
I´ve had the same error when I try run my php file, just change the in next line:
$objWriter->save("/dir1"."/".$file.".xlsx");
for this:
$objWriter->save(dirname(__FILE__)."/dir1"."/".$file.".xlsx");
add the the dir
path and it worked!!!.
回答7:
And my answer is: Filename had symbols such as ":", ",", '"' Had to replace them to different ones. All worked
回答8:
In my case, I modify the permissions of the target folder to rwxrwxrwx (0777) and now works!
回答9:
This error happens also when trying to save a file into a folder that doesn't exist. Make sure the whole path exists.
回答10:
The following works for the Excel2007 format. It would need to be adapted for different formats.
Open this file:
\Classes\PHPExcel\Writer\Excel2007.php
Look near Line 196 for:
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
$pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');
Replace the second line with this:
$pFilename = dirname(\__FILE__).'/'. rand(0, getrandmax()) . rand(0, getrandmax()) . ".phpxltmp";
Then you can use the export-function as described in the developer guide.
回答11:
set chmod 777 -R public/results
回答12:
It's caused by dir permission. Try to enter the final folder, then chmod -R 777 [folder_name]
. It should work :)
来源:https://stackoverflow.com/questions/21436949/phpexcel-writer-exception-with-message-could-not-close-zip-file-php-output