我已经设置了我的php配置设置来上传12800M文件,无限大小文件和上传时间无限以进行测试,但我一直坚持这个常见的PHPExcel致命内存耗尽错误。我收到以下常见错误消息:
致命错误:第1220行的... / Worksheet.php中允许的内存大小为536870912字节(试图分配32个字节)。
当我使用块读取过滤器或迭代器时,随着.xlsx文件被进一步读入行,内存使用量增加而不是保持与我从PHPExcel开发人员读到的内容相同。
我使用的是PHPExcel 1.8.0。我可能会尝试旧版本,因为我已经读过阅读大文件的表现更好。我开始定期加载文件并将其读入数组,使用如示例中的块读取过滤,并使用此URL的迭代器:PHPExcel - memory leak when I go through all rows。我认为如果版本是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 Reader#12中修改的块读取过滤器,它仍然给我带来相同的致命内存耗尽,因为它的内存使用量仍在增加,因为它在行中进一步读取?
<?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>
答案 0 :(得分:1)
这里确实存在一个主要问题:
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
将尝试为工作表的整个大小构建一个数组,无论是否加载了块.... toArray()使用基于您正在加载的文件的电子表格的预期大小,而不是您正在加载的过滤后的一组单元格
尝试仅使用rangeToArray()获取您通过块加载的单元格范围
$sheetData = $objPHPExcel->getActiveSheet()
->rangeToArray(
'A'.$startRow.':'.$objPHPExcel->getActiveSheet()->getHighestColumn().($startRow+$chunkSize-1),
null,
true,
true,
true
);
即便如此,在内存中构建PHP数组会占用大量内存;如果你的代码可以一次处理一行工作表数据而不是填充一个大数组
,那么你的代码将会少得多。