PHPExcel_Writer_Exception 并显示消息“无法关闭 zip 文件 php://output。”

问题描述 投票:0回答:14

我正在使用 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
,其中
$objZip
ZipArchive
类的实例。

问题的原因是什么以及如何解决?谢谢你。

php phpexcel ziparchive
14个回答
44
投票

保存到 php://output 时出现此错误的最常见原因是 open_basedir 限制,该限制不包含有效的系统临时文件夹(例如

/tmp
),或系统临时文件夹的权限... suhosin 也可以即使明显的权限似乎设置正确,也会影响这一点。

一个可能的解决方法是将文件写入文件系统中您知道自己具有完全写入权限的目录中,然后在删除文件之前使用 readfile() 将该文件流式传输到 php://output


28
投票

感谢马克·贝克。他的回答已经解决了问题。我使用他的方法编写了一个简单的辅助方法。

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

我刚刚将

$objWriter->save('php://output')
替换为
SaveViaTempFile($objWriter)


6
投票

嗨,我尝试了以下方法: 在服务器linux Centos 7.0中不指定目录tmp的路由,输入:

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

工作!!


2
投票

对于某些可能有相同错误消息的人:这可能很简单,因为您尝试保存到的文件名实际上已经在 Excel 中打开。 我的情况就是这样吗


2
投票

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

PhpSpreadsheet/Writer/Excel2007.php

解决办法是在Excel2007.php中保存函数

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";

谢谢。


1
投票

当我尝试运行我的 php 文件时,我遇到了同样的错误,只需更改下一行:

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

为此:

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

添加

dir
路径并且它起作用了!!!.


0
投票

我的答案是: 文件名包含“:”、“,”、“”'等符号 不得不将它们更换为不同的。 一切顺利


0
投票

尝试将文件保存到不存在的文件夹时也会发生此错误。确保整个路径存在。


0
投票

就我而言,我只是尝试将文件保存到不存在的文件夹中。创建文件夹,问题解决了。


0
投票

这也可能是由于 PHPExcel(或其替代品 - PhpSpreadsheet)所在目录的所有权问题引起的。

可能导致这种情况发生的示例1 - 您通过 FTP/SFTP 将包含 PHPExcel / PhpSpreadsheet 库的 zip 存档上传到您的网站 / web 应用程序。然后,您通过终端使用

unzip phpexcelarchive.zip -d ./example.com
来提取带有文件的存档。

根据您在解压缩/解压缩存档时登录控制台/终端的方式(root,或具有不同权限的其他类型的用户,属于特定组等),该特定用户将被设置为所有者通过解压缩存档创建的文件和目录。

可能稍后会导致问题,因为它可能限制您可以使用 PHPExcel / PhpSpreadsheet 执行的操作 - 标题错误是可能发生的一件事。

解决方案是以编程方式(使用 PHP 脚本并使用

echo exec('unzip phpexcelarchive.zip -d ./example.com')
)或通过控制面板(cPanel、Plesk 等)及其文件管理器中的内置提取器来解压存档。

这将使您的 Apache(或同等)用户成为解压目录和文件的所有者。


1 您确实应该有一个像这样安装/设置 PHPExcel / PhpSpreadsheet 的充分理由。最好的安装方式是通过 Composer。


-1
投票

以下适用于Excel2007格式。它需要适应不同的格式。


打开此文件:

\Classes\PHPExcel\Writer\Excel2007.php

查看 196 号线附近:

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";

然后您可以按照开发人员指南中的说明使用导出功能。


-1
投票

在我的例子中,我将目标文件夹的权限修改为rwxrwxrwx(0777),现在可以工作了!


-2
投票

这是dir权限造成的。尝试输入最后一个文件夹,然后

chmod -R 777 [folder_name]
。它应该有效:)


-3
投票

设置 chmod 777 -R 公共/结果

© www.soinside.com 2019 - 2024. All rights reserved.