phpexcel 内存耗尽,128Mb 内存只读取大文件的第一行

phpexcel memory exhausted with 128Mb memory reading only first row of a big file

我的 xlsx 文件有大约 95.500 行和 28 列的内存问题。 为了处理这么大的文件(超过 10 MB xlsx),我写了下面的代码,但是当我执行代码并调用加载方法时,即使只读取一行,我也会收到内存耗尽错误! (我只分配了 128Mb 给 php 解释器)

请考虑:

请不要简单地建议增加 php 进程的内存。我已经知道这是可能的,但是 运行 在 VPS 共享服务器上的代码最大只有 512Mb 的 RAM,我需要尽可能保持内存使用率最低

有解决办法吗?请找到我使用的以下代码:

/**  Define a Read Filter class implementing PHPExcel_Reader_IReadFilter  to read file in "chunks" */
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;
    }
}

function loadXLSFile($inputFile){
   // Initiate cache
   $cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_sqlite3;    
   if (!PHPExcel_Settings::setCacheStorageMethod($cacheMethod)) {
       echo date('H:i:s'), " Unable to set Cell Caching using ", $cacheMethod,
                                     " method, reverting to memory", EOL;
   }
    $inputFileType = PHPExcel_IOFactory::identify($inputFile);
    $objReader = PHPExcel_IOFactory::createReader($inputFileType);
    $chunkFilter = new chunkReadFilter();
    //  Tell the Read Filter, the limits on which rows we want to read this iteration
    $chunkFilter->setRows(1,1);
    // Tell the Reader that we want to use the Read Filter that we've Instantiated
    $objReader->setReadFilter($chunkFilter);
    $objReader->setReadDataOnly(true);
    $objPHPExcel = $objReader->load($inputFile);
}

更新

下面是pamelus要求返回的错误

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 112 bytes) in /vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel2007.php on line 471
PHP Stack trace:
PHP   1. {main}() dataimport.php:0
PHP   2. loadFileToDb($inputFile = *uninitialized*, $tabletoupdate = *uninitialized*) dataimport.php:373
PHP   3. PHPExcel_Reader_Excel2007->load($pFilename = *uninitialized*) dataimport.php:231

鉴于您的内存限制较低,我可以建议您使用 PHPExcel 的替代方法来一劳永逸地解决您的问题:Spout。它只需要10MB的内存,所以你应该很好!

您的 loadXLSXFile() 函数将变为:

use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Common\Type;

function loadXLSFile($inputFile) {
    $reader = ReaderFactory::create(Type::XLSX);
    $reader->open($inputFile);

    foreach ($reader->getSheetIterator() as $sheet) {
        foreach ($sheet->getRowIterator() as $row) {
            // $row is the first row of the sheet. Do something with it
            break; // you won't read any other rows
        }
        break; // if you only want to read the first sheet
    }

    $reader->close();
}

就这么简单!无需缓存、过滤器和其他优化:)