Ошибка нехватки памяти при объединении большого количества PDF-файлов с помощью Zend_PDF

Мы используем модуль Zend_PDF в SugarCRM для объединения счетов-фактур в формате PDF, которые создает наша система. Мне удалось успешно объединить несколько PDF-файлов (от 10 до 30 в моих тестах), но мы получаем ошибки памяти, когда пытаемся объединить большее количество PDF-файлов. Ошибка выглядит примерно так:

[30-Jan-2012 14:10:20] Неустранимая ошибка PHP: допустимый размер памяти 268435456 байт исчерпан в /usr/local/src/php-5.3.8/Zend/zend_operators.c:1265 (попытка выделить 68134 байта ) в /srv/www/htdocs/sugar6_mf/Zend/Pdf/Element/Object/Stream.php в строке 442

Вышеупомянутая ошибка возникла, когда мы попытались объединить 457 файлов PDF - это файлы, а не страницы. В конечном итоге нам потребуется объединить 5000 за раз.

Может ли кто-нибудь предложить какую-либо помощь / совет о том, как решить эту проблему?

Если необходимо, спросите, и я опубликую код о том, как создается объединенный PDF-файл.

Спасибо.


person marky    schedule 02.02.2012    source источник


Ответы (1)


Я должен предварить этот ответ, сказав, что я ничего не знаю о SugarCRM - мой ответ основан исключительно на моих знаниях о Zend_Pdf.

Если я правильно понимаю, у вас есть PHP-скрипт (надеюсь, не работающий внутри Apache, учитывая время, необходимое для обработки 5000 файлов), который принимает несколько PDF-файлов в качестве входных данных с использованием метода Zend_Pdf::load() и затем перебирая страницы каждого объекта PDF и добавляя их к одному целевому экземпляру Zend_Pdf, который вы затем записываете в файл, используя метод save().

Используя этот подход, даже если вы unset() добавите каждый из исходных объектов PDF после добавления страниц в целевой объект PDF, вам все равно потребуется достаточно памяти для хранения всего выходного файла. Если вы пропустили 250 МБ всего с 457 файлами, то я предполагаю, что ваши входные PDF-файлы, вероятно, имеют размер около 500 КБ, поэтому ваш выходной файл будет абсолютно огромным, поэтому вам все равно не хватит памяти.

Я бы посоветовал полностью отказаться от этого метода и использовать вместо него pdftk, который можно вызывать с помощью функции exec(). Я уверен, что существует ограничение на размер аргументов, которые вы можете предоставить exec(), поэтому, вероятно, это будет многоэтапный процесс с несколькими промежуточными файлами, но в конечном итоге я думаю, что это будет более быстрое и надежное решение.

И просто чтобы повторить более раннее замечание, я бы не запускал этот процесс в Apache. Я бы настроил задание cron, которое запускается с соответствующими интервалами и сбрасывает выходной файл в безопасную область на вашем веб-сервере/файловом сервере.

person JamesG    schedule 03.02.2012
comment
Спасибо, Джеймс. Мы посмотрим на pdftk. С таким количеством PDF-файлов, которое мы захотим / должны сгенерировать, нам, возможно, даже придется прибегнуть к разбиению слияния на какой-то набор логических фрагментов (например, в алфавитном порядке по клиентам или что-то в этом роде). - person marky; 03.02.2012
comment
Нет проблем - рад помочь. Удачи тебе с твоим проектом! :-) - person JamesG; 06.02.2012
comment
Отчет об обновлении/тестировании. С помощью pdftk мне удалось объединить 1200 PDF-файлов размером от 88 до 350 КБ в один многостраничный PDF-файл весом 3,5 МБ менее чем за 5 секунд. внутри скрипта PHP! Спасибо! - person marky; 07.02.2012