PHPExcel:为 .xlsx、.ods 和 .pdf 生成错误的二进制文件
PHPExcel: Generating wrong binaries for .xlsx, .ods and .pdf
我正在使用 PHPExcel 在一些大型数据阵列上生成 .xlsx、.ods、.pdf 和 .cvs 文件(对于 .pdf 使用 DomPDF)。如果有问题,我会按照他们 github 页面和 Whosebug post 上的示例进行操作。我设法使 .csv 导出工作正常,但其余部分没有。
当 运行 .xlsx 导出时,我得到一个无法在我的 mac 和 google 文档中打开的 .xlsx 文件。因此,我将 php 中的所有 header() 调用注释掉,以便观察任何 PHP 错误消息。原来有 none,我在浏览器中得到了预期的 .xlsx、.pdf 或 .ods 二进制文件,即使我稍后无法打开它们。所以看起来我的脚本正在工作但不知何故产生了损坏的二进制文件。
我在这里做错了什么?下面的代码是我的.xlsx导出的,.pdf/.ods导出的代码差不多。
$excel = new PHPExcel();
// Now set some meta data for that object
// ...
$cellRow = 2;
$cellColumn = "B";
// Add data to the excel file
foreach($entries as $entry) {
// ...
$cellColumn = "B";
$cellRow += 1;
}
// Export
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="export_' . $dateGenerated . '.xlsx"');
header('Cache-Control: max-age=0');
header('Cache-Control: max-age=1');
header('Expires: ' . gmdate('D, d M Y H:i:s'));
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: cache, must-revalidate');
header('Pragma: public');
$writer = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
saveViaTempFile($writer);
saveViaTempFile() 函数取自此 Whosebug post: PHPExcel_Writer_Exception with message "Could not close zip file php://output." 以避免一些其他问题。
TLDR:我正在生成 .xlsx、.ods、.pdf 二进制文件,代码应该是正确的。二进制文件以某种方式损坏。我究竟做错了什么?谢谢!
编辑:根据要求提供更多信息:
我正在使用 PHPExcel 1.8.1。使用 composer 安装并使用 require "vendor/autoload.php";
在我的本地脚本中导入我正在使用 error_reporting(E_ALL);
并且没有抑制任何东西。仍然没有显示任何单一的通知/错误。它只是简单地生成我当时无法打开的 .xlsx。
我正在使用的函数 saveVieTempFile() 是以下函数,直接从上面的链接 SO 线程复制而来:
static function saveViaTempFile($objWriter) {
$filePath = "tmp/" . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
$objWriter->save($filePath);
readfile($filePath);
unlink($filePath);
}
是的,我将 CHMOD(777) 设置为 /tmp 目录。否则我将无法实际接收二进制输出。
我什至测试过如果只向文件添加极其简单的数据是否像这样工作:
$excel->setActiveSheetIndex(0)->setCellValue("A3", "hello");
$excel->setActiveSheetIndex(0)->setCellValue("A4", "world");
$excel->setActiveSheetIndex(0)->setCellValue("A5", "this");
$excel->setActiveSheetIndex(0)->setCellValue("A6", "isn't");
$excel->setActiveSheetIndex(0)->setCellValue("C1", "working");
$excel->setActiveSheetIndex(0);
事实证明,即使是这个简单的数据也没有正确导出,我无法在我的 mac 上或之后使用 google 文档打开这个文件。
更多信息,请在评论中提问,我会更新这个post。
原来我的问题在某种程度上与 "possible duplicate" post 链接有关。我有一个中央 appIndex.php,其中包含很多我需要的东西。然后这个中心站点包括我当前要执行的站点 - 例如 excelExport.php。
因为我的中央页面使用了 ob_start();和 ob_end_flush();我的 .xlsx 和 .ods 导出无效。第二个我删除了 ob_start();我的导出立即起作用。
我正在使用 PHPExcel 在一些大型数据阵列上生成 .xlsx、.ods、.pdf 和 .cvs 文件(对于 .pdf 使用 DomPDF)。如果有问题,我会按照他们 github 页面和 Whosebug post 上的示例进行操作。我设法使 .csv 导出工作正常,但其余部分没有。
当 运行 .xlsx 导出时,我得到一个无法在我的 mac 和 google 文档中打开的 .xlsx 文件。因此,我将 php 中的所有 header() 调用注释掉,以便观察任何 PHP 错误消息。原来有 none,我在浏览器中得到了预期的 .xlsx、.pdf 或 .ods 二进制文件,即使我稍后无法打开它们。所以看起来我的脚本正在工作但不知何故产生了损坏的二进制文件。
我在这里做错了什么?下面的代码是我的.xlsx导出的,.pdf/.ods导出的代码差不多。
$excel = new PHPExcel();
// Now set some meta data for that object
// ...
$cellRow = 2;
$cellColumn = "B";
// Add data to the excel file
foreach($entries as $entry) {
// ...
$cellColumn = "B";
$cellRow += 1;
}
// Export
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="export_' . $dateGenerated . '.xlsx"');
header('Cache-Control: max-age=0');
header('Cache-Control: max-age=1');
header('Expires: ' . gmdate('D, d M Y H:i:s'));
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: cache, must-revalidate');
header('Pragma: public');
$writer = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
saveViaTempFile($writer);
saveViaTempFile() 函数取自此 Whosebug post: PHPExcel_Writer_Exception with message "Could not close zip file php://output." 以避免一些其他问题。
TLDR:我正在生成 .xlsx、.ods、.pdf 二进制文件,代码应该是正确的。二进制文件以某种方式损坏。我究竟做错了什么?谢谢!
编辑:根据要求提供更多信息:
我正在使用 PHPExcel 1.8.1。使用 composer 安装并使用 require "vendor/autoload.php";
在我的本地脚本中导入我正在使用 error_reporting(E_ALL);
并且没有抑制任何东西。仍然没有显示任何单一的通知/错误。它只是简单地生成我当时无法打开的 .xlsx。
我正在使用的函数 saveVieTempFile() 是以下函数,直接从上面的链接 SO 线程复制而来:
static function saveViaTempFile($objWriter) {
$filePath = "tmp/" . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
$objWriter->save($filePath);
readfile($filePath);
unlink($filePath);
}
是的,我将 CHMOD(777) 设置为 /tmp 目录。否则我将无法实际接收二进制输出。
我什至测试过如果只向文件添加极其简单的数据是否像这样工作:
$excel->setActiveSheetIndex(0)->setCellValue("A3", "hello");
$excel->setActiveSheetIndex(0)->setCellValue("A4", "world");
$excel->setActiveSheetIndex(0)->setCellValue("A5", "this");
$excel->setActiveSheetIndex(0)->setCellValue("A6", "isn't");
$excel->setActiveSheetIndex(0)->setCellValue("C1", "working");
$excel->setActiveSheetIndex(0);
事实证明,即使是这个简单的数据也没有正确导出,我无法在我的 mac 上或之后使用 google 文档打开这个文件。
更多信息,请在评论中提问,我会更新这个post。
原来我的问题在某种程度上与 "possible duplicate" post 链接有关。我有一个中央 appIndex.php,其中包含很多我需要的东西。然后这个中心站点包括我当前要执行的站点 - 例如 excelExport.php。
因为我的中央页面使用了 ob_start();和 ob_end_flush();我的 .xlsx 和 .ods 导出无效。第二个我删除了 ob_start();我的导出立即起作用。