PHPExcel 1.8.0在加载、块读取和迭代器时耗尽内存

PHPExcel 1.8.0在加载、块读取和迭代器时耗尽内存,php,excel,memory,Php,Excel,Memory,我已经将我的php配置设置为上载12800M文件、无限大小文件和上载无限时间进行测试,但我一直被这个常见的PHPExcel致命内存耗尽错误所困扰。我收到以下常见错误消息: 致命错误:第1220行的…/sheetwork.php中允许的内存大小536870912字节已用完(尝试分配32字节) 当我使用区块读取过滤器或迭代器时,随着.xlsx文件被进一步读取到行中,内存使用会增加,而不是像我从PHPExcel开发人员那里读到的报告一样 我使用的是phpexcel1.8.0。我可能会尝试一个旧版本,因

我已经将我的php配置设置为上载12800M文件、无限大小文件和上载无限时间进行测试,但我一直被这个常见的PHPExcel致命内存耗尽错误所困扰。我收到以下常见错误消息:

致命错误:第1220行的…/sheetwork.php中允许的内存大小536870912字节已用完(尝试分配32字节)

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

我使用的是phpexcel1.8.0。我可能会尝试一个旧版本,因为我读到读取大文件的性能更好。我从一个常规的加载开始,将文件读入一个数组,使用块读取过滤(如示例所示),并在以下URL处使用迭代器:。我认为它是版本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 />";
    }

}

您确实遇到了一个主要问题:

$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
它将尝试为工作表的整个大小构建一个数组,而不管是否加载了块。。。。toArray()使用基于加载的文件的电子表格的预期大小,而不是加载的筛选单元格集

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


即使如此,在内存中构建PHP数组也会占用大量内存;如果您的代码可以一次处理一行工作表数据,而不是填充一个大数组,那么您的代码将大大减少内存消耗

在您发布的代码中不使用分块,因此我无法对此发表评论;但是你看过单元缓存吗?代码在哪里失败了?它是否加载了文件(块或其他)?还是在加载过程中?对不起,我已经在第二个代码段中包含了分块。我已经看过了手机缓存。我注意到这个致命的内存耗尽错误有任何改进。第一个代码在加载大于2MB的文件时失败。您应该断开工作表的连接,并在下一个区块迭代之前在循环中处理当前PHPExcel对象后将其取消设置,如文档中所述。。。。。请注意,分块并没有消除所有内存使用,但它确实减少了itI的使用。我已经尝试实现$objPHPExcel->disconnectWorksheets();未设置($objPHPExcel,$sheetData);在for循环迭代之后,我仍然得到完全相同的致命内存耗尽错误…我仍然使用rangToArray而不是toArray得到致命内存耗尽错误。似乎RangeTarray遇到了与toArray相同的问题。您要求的范围是什么?在内存中构建PHP数组需要大量内存一次处理一行工作表数据要比在memoryStrange中构建一个大数组好得多,我在LAMP堆栈上运行它,而不是在我使用的WAMP堆栈上运行,LAMP堆栈上没有问题。我可能遇到了Windows操作系统内存管理问题。
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
$sheetData = $objPHPExcel->getActiveSheet()
    ->rangeToArray(
        'A'.$startRow.':'.$objPHPExcel->getActiveSheet()->getHighestColumn().($startRow+$chunkSize-1),
        null,
        true,
        true,
        true
    );