PHPExcel 1.8.0内存耗尽,读取块和迭代器

我已经设置我的PHPconfiguration设置上传12800M文件,无限大小的文件,并上传时间无限testing,但我一直坚持这个常见的PHPExcel致命内存耗尽错误。 我收到以下常见错误消息:

致命错误:在第1220行的… / Worksheet.php中,允许内存大小为536870912个字节(尽力分配32个字节)。

当我使用块读取filter或迭代器时,随着.xlsx文件被进一步读入行中,内存使用量增加,而不是像我从PHPExcel开发人员那里读到的报告那样保持不变。

我在PHPExcel 1.8.0上。 我可能会尝试一个较旧的版本,因为我已经阅读,阅读大文件performance更好。 我开始定期加载文件,并将其读入数组中,使用块读取过滤(如示例中所示),并在此URL处使用迭代器: PHPExcel – 当我遍历所有行时发生内存泄漏 。 如果是1.8.0或更高版本,我会认为它并不重要。

<?php /** Error reporting */ error_reporting(E_ALL); ini_set('display_errors', TRUE); ini_set('display_startup_errors', TRUE); date_default_timezone_set('America/Los_Angeles'); define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />'); /** Include PHPExcel_IOFactory */ require_once dirname(__FILE__) . '/../Classes/PHPExcel/IOFactory.php'; if (!file_exists("Test.xlsx")) { exit("Please check if Test.xlsx exists first.\n"); } echo date('H:i:s') , " Load workbook from Excel5 file" , EOL; $callStartTime = microtime(true); $objPHPExcel = PHPExcel_IOFactory::load("Order_Short.xls"); $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo 'Call time to load Workbook was ' , sprintf('%.4f',$callTime) , " seconds" , EOL; // Echo memory usage echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL; //http://runnable.com/Uot2A2l8VxsUAAAR/read-a-simple-2007-xlsx-excel-file-for-php // Read your Excel workbook $inputFileName="Drybar Client Data for Tableau Test.xlsx"; $table = "mt_company2_project2_table144_raw"; try { echo date('H:i:s') , " Load workbook from Excel5 file" , EOL; $callStartTime = microtime(true); $inputFileType = PHPExcel_IOFactory::identify($inputFileName); $objReader = PHPExcel_IOFactory::createReader($inputFileType); $objPHPExcel = $objReader->load($inputFileName); $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo 'Call time to load Workbook was ' , sprintf('%.4f',$callTime) , " seconds\r\n" , EOL; // Echo memory usage echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL; } catch (Exception $e) { die('Error loading file "' . pathinfo($inputFileName, PATHINFO_BASENAME) . '": ' . $e->getMessage()); } // Get worksheet dimensions $sheet = $objPHPExcel->getSheet(0); // http://asantillan.com/php-excel-import-to-mysql-using-phpexcel/ $worksheetTitle = $sheet->getTitle(); $highestRow = $sheet->getHighestRow(); $highestColumn = $sheet->getHighestColumn(); $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn); // Calculationg Columns $nrColumns = ord($highestColumn) - 64; echo "File ".$worksheetTitle." has "; echo $nrColumns . ' columns'; echo ' x ' . $highestRow . ' rows.<br />'; // Loop through each row of the worksheet in turn for ($row = 1; $row <= $highestRow; $row++) { // Read a row of data into an array $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, FALSE, FALSE); var_dump($rowData); foreach ($rowData[0] as $k => $v) { echo "Row: " . $row . "- Col: " . ($k + 1) . " = " . $v . "<br />"; } } 

我包含从PHPExcel读取器示例#12修改的块读取filter,仍然给我相同的致命内存耗尽,因为它的内存使用量仍然增加,因为它进一步向下读取行?

 <?php error_reporting(E_ALL); set_time_limit(0); define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />'); date_default_timezone_set('America/Los_Angeles'); /** Set Include path to point at the PHPExcel Classes folder **/ set_include_path(get_include_path() . PATH_SEPARATOR . '../../../Classes/'); /** Include PHPExcel_IOFactory **/ include 'PHPExcel/IOFactory.php'; $inputFileName = 'Test.xlsx'; /** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter */ class chunkReadFilter implements PHPExcel_Reader_IReadFilter { private $_startRow = 0; private $_endRow = 0; /** Set the list of rows that we want to read */ public function setRows($startRow, $chunkSize) { $this->_startRow = $startRow; $this->_endRow = $startRow + $chunkSize; } public function readCell($column, $row, $worksheetName = '') { // Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow)) { return true; } return false; } } $inputFileType = PHPExcel_IOFactory::identify($inputFileName); $callStartTime = microtime(true); echo 'Loading file ',pathinfo($inputFileName,PATHINFO_BASENAME),' using IOFactory with a defined reader type of ',$inputFileType,'<br />'; // Call time $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo 'Call time to read Workbook was ' , sprintf('%.4f',$callTime) , " seconds" , EOL; // Echo memory usage echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL; /** Create a new Reader of the type defined in $inputFileType **/ $objReader = PHPExcel_IOFactory::createReader($inputFileType); echo '<hr />'; /** Define how many rows we want to read for each "chunk" **/ $chunkSize = 100; /** Create a new Instance of our Read Filter **/ $chunkFilter = new chunkReadFilter(); /** Tell the Reader that we want to use the Read Filter that we've Instantiated **/ $objReader->setReadFilter($chunkFilter); /** Loop to read our worksheet in "chunk size" blocks **/ for ($startRow = 2; $startRow <= 26000; $startRow += $chunkSize) { echo 'Loading WorkSheet using configurable filter for headings row 1 and for rows ',$startRow,' to ',($startRow+$chunkSize-1),'<br />'; /** Tell the Read Filter, the limits on which rows we want to read this iteration **/ $chunkFilter->setRows($startRow,$chunkSize); /** Load only the rows that match our filter from $inputFileName to a PHPExcel Object **/ $objPHPExcel = $objReader->load($inputFileName); // Do some processing here $sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true); echo '<br /><br />'; // Call time $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo 'Call time to read Workbook was ' , sprintf('%.4f',$callTime) , " seconds" , EOL; // Echo memory usage echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL; // Echo memory peak usage echo date('H:i:s') , " Peak memory usage: " , (memory_get_peak_usage(true) / 1024 / 1024) , " MB" , EOL; echo '<hr />'; } ?> <body> </html> 

你在这里有一个主要的问题:

 $sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true); 

这将尝试为整个工作表的大小build立一个数组,无论你是否加载或不加载…. toArray()使用基于你正在加载的文件的电子表格的预期大小,而不是过滤的设置你正在加载的单元格

尝试仅使用rangeToArray()获取通过块加载的单元格范围

 $sheetData = $objPHPExcel->getActiveSheet() ->rangeToArray( 'A'.$startRow.':'.$objPHPExcel->getActiveSheet()->getHighestColumn().($startRow+$chunkSize-1), null, true, true, true ); 

即使如此,在内存中构buildPHP数组也需要大量的内存。 如果您的代码可以一次处理一行工作表数据,而不是填充大数组