PHPExcel_Writer_Exception的错误信息为“无法关闭zip文件php://output。”。

29

我正在使用PHPExcel将一些数据导出到Excel文件中,并希望在创建完成后立即向用户发送Excel文件。这是我的测试代码:

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();
}

在我的本地服务器上 (Windows 7 x64, Php 5.3.8, Apache 2.2.21),我可以得到一个有效的xlsx文件,没有错误。 但是在生产服务器上出现了问题 (Linux 2.6.32-5-amd64, PHP 5.3.3-7+squeeze13, Apache 2.2.16)。脚本会让浏览器下载名为"export.xlsx"的文件,但内容不正确。

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没有运行在安全模式中。"open_basedir"选项为空(已被注释掉)。

我在PHPExcel文件中发现了这样的代码:

if ($objZip->close() === false) {
    throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename.");
}

问题的原因是 $objZip->close() === false,其中$objZipZipArchive类的一个实例。

问题的原因是什么,我该如何解决?谢谢。

13个回答

44
保存到php://output时出现此错误的最常见原因是开启了open_basedir限制,该限制不包括有效的系统临时文件夹(例如 /tmp),或者对于系统的临时文件夹缺少权限...即使明显的权限设置正确,suhosin也可能会影响它。
一个可能的解决方法是将文件写入你知道自己具有完全写入权限的文件系统目录中,然后使用readfile()函数将该文件流式传输到php://output中,最后再删除该文件。

生产服务器上安装了Suhosin,但本地服务器没有安装。因此,Suhosin可能会引起问题。但我不想深究它。如你的建议,我想简单地使用临时文件来解决问题。谢谢! - Pavel L
在我的情况下,我有一个错别字.. :< 因此请确保你没有任何错误。 - Rangi Lin
2
嘿,我遇到了同样的错误。我尝试将 /tmp 和 /var/tmp 设置为 777,但并没有起作用。你是怎么做到的? - muuvmuuv
1
第一个点(./)确保路径相对于当前工作文件夹;第二个点(export_123.xlsx)是文件名和文件扩展名之间的分隔符。 - Mark Baker
如果你想要保存到文件,请注意,你必须使用mkdir()函数创建完整的父路径,否则你会得到ZipArchive::close(): No error in ...错误,因为Excel2007不会在不存在路径的情况下创建路径。 - Serhii Popov
显示剩余2条评论

28

感谢Mark Baker。他的回答解决了问题。我使用他的方法编写了一个简单的辅助方法。

static function SaveViaTempFile($objWriter){
    $filePath = sys_get_temp_dir() . "/" . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
}

我刚刚用SaveViaTempFile($objWriter)替换了$objWriter->save('php://output')


听起来很不错,但你需要在哪里进行替换呢? - molerat

6

您好,我尝试了以下操作:在一个Centos 7.0的Linux服务器上,没有指定tmp目录的路径,输入:

function SaveViaTempFile($objWriter){
    $filePath = '' . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
    exit;
}

and work !!


它对我没用。 - Alex78191

2

优秀的朋友在php 7.1.2中为我工作,并使用PhpSpreadsheet修复了同一文件。

PhpSpreadsheet/Writer/Excel2007.php

解决方案在Excel2007.php中的save函数中。
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
    $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');

将第二行替换为以下内容:
$pFilename = dirname(__FILE__).'/'. rand(0, getrandmax()) . rand(0, getrandmax()) . ".phpxltmp";

thanks.


2

对于一些人可能会遇到相同的错误信息:这可能很简单,因为您正在尝试保存的文件名实际上已经在您的Excel中打开了。这是我的情况。


这在我的情况下也是如此,所以可能会发生在其他人身上,指出来很好。 - Rakibul Haq

1

当我尝试运行我的php文件时,遇到了相同的错误,请在下一行更改:

$objWriter->save("/dir1"."/".$file.".xlsx");

对于这个:
$objWriter->save(dirname(__FILE__)."/dir1"."/".$file.".xlsx");

添加dir路径,然后就可以工作了!!!

0

我的答案是: 文件名中有诸如“:”,“,”,“””等符号 必须将它们替换为不同的符号。 一切都正常工作了


0

当尝试将文件保存到不存在的文件夹中时,也会出现此错误。确保整个路径存在。


0
在我的情况下,我只是尝试将文件保存到一个不存在的文件夹中。创建了文件夹,问题就解决了。

你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人能够确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Community

-1
在我的情况下,我将目标文件夹的权限修改为rwxrwxrwx(0777),现在可以正常工作了!

您永远不应该把服务器目录配置成全世界都可读可写的状态。 - ZeWaren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接