【问题标题】:Allowed memory size of 134217728 bytes exhausted in PhpExcel [duplicate]PhpExcel中允许的内存大小为134217728字节[重复]
【发布时间】:2013-10-20 20:09:31
【问题描述】:

我使用 phpexcel 导出文件 xlsx,数据有 32 列和许多行。每天数据都在增加,所以数据会非常大。这是我的代码:

$filename="data.xlsx";
            $cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_phpTemp;
            $cacheSettings = array( 'memoryCacheSize' => '128MB');
            PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
            ini_set('max_execution_time', 123456);
            $objPHPExcel = new PHPExcel();
            $objPHPExcel->setActiveSheetIndex(0);
            $i = 2;
            $objPHPExcel->getActiveSheet()->setCellValue('A1', 'Header1');
            $objPHPExcel->getActiveSheet()->setCellValue('B1', 'Header2');
            $objPHPExcel->getActiveSheet()->setCellValue('C1', 'Header3');
            $objPHPExcel->getActiveSheet()->setCellValue('D1', 'Header4');
            $objPHPExcel->getActiveSheet()->setCellValue('E1', 'Header5');
            $objPHPExcel->getActiveSheet()->setCellValue('F1', 'Header6');
            $objPHPExcel->getActiveSheet()->setCellValue('G1', 'Header7');
            $objPHPExcel->getActiveSheet()->setCellValue('H1', 'Header8');
            $objPHPExcel->getActiveSheet()->setCellValue('I1', 'Header9');
            $objPHPExcel->getActiveSheet()->setCellValue('J1', 'Header10');
            $objPHPExcel->getActiveSheet()->setCellValue('K1', 'Header11');
            $objPHPExcel->getActiveSheet()->setCellValue('L1', 'Header12');
            $objPHPExcel->getActiveSheet()->setCellValue('M1', 'Header13');
            $objPHPExcel->getActiveSheet()->setCellValue('N1', 'Header14');
            $objPHPExcel->getActiveSheet()->setCellValue('O1', 'Header15');
            $objPHPExcel->getActiveSheet()->setCellValue('P1', 'Header16');
            $objPHPExcel->getActiveSheet()->setCellValue('Q1', 'Header17');
            $objPHPExcel->getActiveSheet()->setCellValue('R1', 'Header18');
            $objPHPExcel->getActiveSheet()->setCellValue('S1', 'Header19');
            $objPHPExcel->getActiveSheet()->setCellValue('T1', 'Header20');
            $objPHPExcel->getActiveSheet()->setCellValue('U1', 'Header21');
            $objPHPExcel->getActiveSheet()->setCellValue('V1', 'Header22');
            $objPHPExcel->getActiveSheet()->setCellValue('W1', 'Header23');
            $objPHPExcel->getActiveSheet()->setCellValue('X1', 'Header24');
            $objPHPExcel->getActiveSheet()->setCellValue('Y1', 'Header25');
            $objPHPExcel->getActiveSheet()->setCellValue('Z1', 'Header26');
            $objPHPExcel->getActiveSheet()->setCellValue('AA1', 'Header27');
            $objPHPExcel->getActiveSheet()->setCellValue('AB1', 'Header28');
            $objPHPExcel->getActiveSheet()->setCellValue('AC1', 'Header29');
            $objPHPExcel->getActiveSheet()->setCellValue('AD1', 'Header30');
            $objPHPExcel->getActiveSheet()->setCellValue('AE1', 'Header31');
            $objPHPExcel->getActiveSheet()->setCellValue('AF1', 'Header32');
            foreach ($data as $value) {
                $objPHPExcel->getActiveSheet()->setCellValue('A'.$i, $value['1']);
                $objPHPExcel->getActiveSheet()->setCellValue('B'.$i, $value['2']);
                $objPHPExcel->getActiveSheet()->setCellValue('C'.$i, $value['3']);
                $objPHPExcel->getActiveSheet()->setCellValue('D'.$i, $value['4']);
                $objPHPExcel->getActiveSheet()->setCellValue('E'.$i, $value['5']);
                $objPHPExcel->getActiveSheet()->setCellValue('F'.$i, $value['6']);
                $objPHPExcel->getActiveSheet()->setCellValue('G'.$i, $value['7']);
                $objPHPExcel->getActiveSheet()->setCellValue('H'.$i, $value['8']);
                $objPHPExcel->getActiveSheet()->setCellValue('I'.$i, $value['9']);
                $objPHPExcel->getActiveSheet()->setCellValue('J'.$i, $value['10']);
                $objPHPExcel->getActiveSheet()->setCellValue('K'.$i, $value['11']);
                $objPHPExcel->getActiveSheet()->setCellValue('L'.$i, $value['12']);
                $objPHPExcel->getActiveSheet()->setCellValue('M'.$i, $value['13']);
                $objPHPExcel->getActiveSheet()->setCellValue('N'.$i, $value['14']);
                $objPHPExcel->getActiveSheet()->setCellValue('O'.$i, $value['15']);
                $objPHPExcel->getActiveSheet()->setCellValue('P'.$i, $value['16']);
                $objPHPExcel->getActiveSheet()->setCellValue('Q'.$i, $value['17');
                $objPHPExcel->getActiveSheet()->setCellValue('R'.$i, $value['18']);
                $objPHPExcel->getActiveSheet()->setCellValue('S'.$i, $value['19']);
                $objPHPExcel->getActiveSheet()->setCellValue('T'.$i, $value['20']);
                $objPHPExcel->getActiveSheet()->setCellValue('U'.$i, $value['21']);
                $objPHPExcel->getActiveSheet()->setCellValue('V'.$i, $value['22']);
                $objPHPExcel->getActiveSheet()->setCellValue('W'.$i, $value['23']);
                $objPHPExcel->getActiveSheet()->setCellValue('X'.$i, $value['24']);
                $objPHPExcel->getActiveSheet()->setCellValue('Y'.$i, $value['25']);
                $objPHPExcel->getActiveSheet()->setCellValue('Z'.$i, $value['26']);
                $objPHPExcel->getActiveSheet()->setCellValue('AA'.$i, $value['27']);
                $objPHPExcel->getActiveSheet()->setCellValue('AB'.$i, $value['28']);
                $objPHPExcel->getActiveSheet()->setCellValue('AC'.$i, $value['29']);
                $objPHPExcel->getActiveSheet()->setCellValue('AD'.$i, $value['30']);
                $objPHPExcel->getActiveSheet()->setCellValue('AE'.$i, $value['31']);
                $objPHPExcel->getActiveSheet()->setCellValue('AF'.$i, $value['32']);
                $i++;
            }
            $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
            ob_end_clean();
            header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            header("Content-Disposition: attachment; filename=".$filename);
            header('Cache-Control: max-age=0');
            $objWriter->setUseDiskCaching(true);
            $objWriter->save("php://output");

两天前,它运行良好。但是今天,它抛出了一个异常: 致命错误:第 155 行 /..../Classes/PHPExcel/CachedObjectStorage/CacheBase.php 中允许的内存大小为 134217728 字节已用尽(尝试分配 85 个字节)

【问题讨论】:

  • 既然您实际上并没有使用 Excel 的任何功能,为什么不简单地编写一个 csv 文件
  • 哦,我认为导出文件 csv 实际上很简单,所以我想尝试使用文件 excel,但我遇到了问题。
  • PHPExcel 在内存不足时无法创建内存,它可以做的最好的事情是通过单元缓存减少内存占用(以执行速度为代价)。我的估计是每个单元格大约 1k 或内存使用量,当您需要编写工作簿时,它会增加一倍。单元缓存可以帮助减少 1k/单元,但有时您可能仍需要增加 PHP 可用的内存

标签: php phpexcel php-extension


【解决方案1】:

另外需要注意的是,您正在通过一个名为 $data.... 的数组循环来构建 PHPExcel 对象。我猜它是通过循环数据库查询的结果构建的。 /p>

$data 数组也将使用您的大部分内存,随着结果数量的增加,内存每天会越来越多。

如果不是循环访问数据库结果集来构建一个大数组,然后循环访问该数组来构建 PHPExcel 数据,而是循环访问数据库结果集并直接构建 PHPExcel 数据,那么效率会更高。这消除了 $data 的内存开销,并将 2 个循环减少到 1 个。

【讨论】:

  • 这真是个好主意,我已经做到了。但是以后如果数据增加超过100000或10000000行,有什么办法解决内存泄漏?
  • 你不能完全消除内存使用,更多的行会增加所需的内存;虽然我推荐 SQLite 缓存,它根本不需要在内存中维护任何单元格索引......但你肯定需要在某些时候增加你的 PHP 内存限制......单元格缓存允许你挤压一个夸脱装进品脱罐,但它不会把一加仑装进品脱罐
  • 如果这是通过网络请求生成的,您可能还需要将其切换到后台任务....行越多,到达您需要的时间越长如果是网络请求,可能会开始超时
  • 感谢您的回答
【解决方案2】:

请记住,除了 PHPExcel 对象使用的内存之外,PHP 还使用内存以及脚本本身。

如果您使用 memoryCacheSize 设置 cache_to_phpTemp,PHPExcel 对象将使用内存达到该限制,然后切换到使用临时文件。您的 memoryCacheSize 与您的绝对 php.ini 内存限制 (128MB) 相同,因此 PHPExcel 在达到 PHP 自己的限制之前永远不会切换到使用临时文件单元缓存。尝试设置较低的 memoryCacheSize(例如 64MB),这样至少 PHPExcel 将有机会缓存​​单元格并减少其自身的内存使用量。

【讨论】:

  • 哦,我尝试将 momoryCacheSize 设置为 8Mb 或 64Mb 但仍然出错
  • 您是否尝试过任何其他缓存方法?除了 SQLite 之外,它们都维护一个“内存中的单元格索引”,因此它们并没有消除内存使用,而是简单地减少它。有些比其他的内存效率更高,但通常需要在内存和速度之间进行权衡。
  • 我还没有尝试过其他缓存方法,因为我不知道其他缓存方法。
  • 这就是阅读文档有帮助的地方......开发者文档中有一个完整的部分列出了不同的缓存方法以及如何使用它们
猜你喜欢
  • 2011-07-30
  • 1970-01-01
  • 2017-01-05
  • 2012-08-29
  • 2017-08-26
  • 2015-09-23
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
相关资源
最近更新 更多