PHPExcel превышает использование памяти только с файлами XLS

У меня проблема с памятью PHPExcel при обработке файла XLS.
Мне приходится работать с довольно большими файлами (от 50 до 200 тыс. Строк и 9-10 столбцов), поэтому мне пришлось использовать ReadFilters для решения проблемы с памятью.

Однако, хотя он довольно хорошо работал с файлами XLSX, используя смесь фоновых процессов и некоторые простые вычисления для размера чанка, я не могу заставить его работать с файлами XLS.

Это кусок кода, где все взрывается:

Class ExcelReadFilter implements PHPExcel_Reader_IReadFilter
{
private $startRow = 0;
private $endRow = 0;

public function setRows($startRow, $chunkSize) {
$this->startRow    = $startRow;
$this->endRow        = $startRow + $chunkSize;
}

public function readCell($column, $row, $worksheetName = '') {
if ( ($row >= $this->startRow && $row < $this->endRow) ) {
return true;
}
return false;
}
}

PHPExcel_Settings::setCacheStorageMethod( PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized );

....
$filter = new ExcelReadFilter();
$filter->setRows($desde, $cuantas);

$reader = PHPExcel_IOFactory::createReader($this->file_type);

$reader->setLoadSheetsOnly($sheet_name);
$reader->setReadDataOnly(false);
$reader->setReadFilter($filter);

$chunk = $reader->load($this->file);
$chunk->setActiveSheetIndexByName($sheet_name);

$active_sheet = $chunk->getActiveSheet();
$rowIterator = $active_sheet->getRowIterator($desde);
$this->num_filas = $active_sheet->getHighestRow();

Сразу после этого я включил следующие строки, чтобы лучше понять, что происходит:

ob_start();
var_dump($rowIterator);

$f = fopen("excel-info.txt", "w");
fwrite($f, ob_get_clean());
fclose($f);

ob_end_clean();
die;

И я думаю, что это указывало на то, где проблема с памятью.
Когда я впервые загрузил оригинальный файл XLS, файл excel-info.txt имел размер 13M.
Затем я открыл файл XLS и сохранил его как XLSX, и повторил процесс, после чего в excel-info.txt было всего 285 Кбайт.

Можно ли как-то изменить эти фильтры для работы с файлами XLS?

Да, и установка предела памяти PHP на более высокое значение не является опцией, но время выполнения не критично.

ADDED

Когда я использовал разные параметры кэширования памяти, я смог уменьшить использование памяти, достаточное для ее работы, и в большинстве случаев сохранил ее до приемлемого размера.

Прямо сейчас я использую PHPExcel_CachedObjectStorageFactory :: cache_to_sqlite, и, кажется, этого достаточно, чтобы он работал.

Хочу заметить, что мои расчеты над сериализованной информацией, помещенной в файл, были неверными.
Файлы Excel5 создают массив с таким количеством записей, сколько строк имеет файл excel, все его значения которого не соответствуют условию фильтра, установленному в NULL. Конечно, когда я сохраняю его в текстовый файл, что-то вроде …

array(10) {
["A"]=>
NULL
["B"]=>
NULL
["C"]=>
NULL
["D"]=>
NULL
["E"]=>
NULL
["F"]=>
NULL
["G"]=>
NULL
["H"]=>
NULL
["I"]=>
NULL
["J"]=>
NULL
}

…занимает много места в файле, но не в php_memory, так что это была моя ошибка.

Теперь я использую этот код для отслеживания использования памяти:

for ( $i=1; $i < 20000; $i+=5000 ){
$filter->setRows($i, 5000);
echo "\n1- Usage: ".(memory_get_usage ()/1024)/1024;
$objPHPExcel = $reader->load($this->file);
echo "\n2- Usage: ".(memory_get_usage ()/1024)/1024;
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
unset($sheetData);
unset($objPHPExcel);
echo "\n3- Usage: ".(memory_get_usage ()/1024)/1024;
}

С определенным файлом XLS он показывает:

1-я итерация
1- Использование: 4.3859634399414
2- Использование: 34.292671203613
3- Использование: 34.68034362793

2-я итерация
1- Использование: 34.68034362793
2- Использование: 34.68293762207
3- Использование: 34.684982299805

И тот же файл, после сохранения как XLSX:

1-я итерация
1- Использование: 4.2780990600586
2- Использование: 6.9042129516602
3- Использование: 7.2916641235352

2-я итерация
1- Использование: 7.2916641235352
2- Использование: 7.5115432739258
3- Использование: 7.2813568115234

Однако я должен сказать, что после сохранения в формате XLSX размер уменьшается примерно вдвое, поэтому я не могу сказать, является ли это ошибкой или ожидаемым поведением.

8

Решение

PHPExcel это боров памяти. Я использовал его для нескольких клиентов и обнаружил, что вам нужно поэкспериментировать с настройкой лимита памяти php, чтобы найти подходящее место, где он может загрузить средний файл, который клиент может импортировать. Мне пришлось использовать целых 8 ГБ на некоторых проектах. Конечно, вы делаете это в подпрограмме, которая загружает файл xls, используя
ini_set (‘memory_limit’, ’16M’), а не в файле php.ini.

Вы пробовали setReadDataOnly (правда)?

Я думаю, что причина в том, что файлы xls — это не просто данные в формате csv, но и универсальная информация для множества другой информации (например, шрифтов и макросов). Когда вы загружаете файл, PHPExcel пытается загрузить все части в память, создавая огромную структуру.

3

Другие решения

Просто добавьте эту строку (например)

ini_set ( ‘memory_limit’, ‘254m’);

это решит проблему с памятью ..

не стесняйтесь изменять предел памяти, чтобы сделать его подходящим для вашего случая

0

По вопросам рекламы [email protected]