mpdf / mpdf

PHP library generating PDF files from UTF-8 encoded HTML
https://mpdf.github.io
GNU General Public License v2.0
4.4k stars 1.07k forks source link

Generating pdfs in a loop causes several issues (memory leak, huge files) #1896

Closed marhyno closed 1 year ago

marhyno commented 1 year ago

Guidelines

Description of the bug

Hello I am trying to build a loop where I want to generate 1000 pdfs from a html template. I came accross two issues. Because my server has only limited memory 256MB and 120 seconds of running script. I dont want to put instantiating of the mpdf class in the loop because it wastes memory and if I run GC after every iteration it runs longer than 120seconds. Logically I would put mpdf class outside of the loop and change only necessary stuff in my html template which then I will write and output to a pdf file. But I have this problem that only first PDF is generated properly and every single one after that doesnt have IMAGES (like a background image) and for some reason every new pdf has bunch of new pages inside of it. I somehow cannot find whats the solution to this problem.

MPDF version - 8.0.17 PHP version - 8.0.28

And these are the files that are generated. Am I missing something ? image As i said the first one is okay, every single new doesnt have images and bunch of new pages. I am running it inside of a plugin for wordpress I am developing. Thank you in advance.

mPDF version

8.0.17

PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)

8.0.28, localhost, laptop, xampp, composer

Reproducible PHP+CSS+HTML snippet suffering by the error

$mpdf = new Mpdf(['format' => [297, 180],
'margin_left' => 0,
'margin_right' => 0,
'margin_top' => 0,
'margin_bottom' => 0,
'margin_bottom_collapse' => true,
'margin_header' => 0,
'margin_footer' => 0,
'fontdata' => $fontData + [ // lowercase letters only in font key
    'algerian' => [
        'R' => 'Algerian Regular.ttf'
    ],
    'monotypecorsiva' => [
        'R' => 'mtcorsva.ttf'
    ],
    'sourceserifprosemibold' => [
        'R' => 'SourceSerifPro-SemiBold.ttf'
    ]
],
'default_font' => 'calibri',
'debug' => false]);

$mpdf->AddFontDirectory(dirname(__FILE__)."/fonts/");
$mpdf->SetDefaultBodyCSS('background', "url('".plugin_dir_url(__FILE__)."pdfCertificates/certifikat-pozadie.png')");
$mpdf->SetDefaultBodyCSS('background-image-resize','6');
$mpdf->defaultheaderline = 0;
$mpdf->defaultfooterline = 0;

$resultOfEmails = [];

$timerStart = microtime(true);
for ($i=0; $i < 1000; $i++) {
    $certificateName = "Certifikát-".getTimeStamp().$i.".pdf";
    $urlCertificateLocation = wp_upload_dir()["baseurl"]."/pdfCertificates/".$certificateName;

    $serverPathCertificate = $upload_location.$certificateName;

    $personalizedCertificate = $certificateTemplate; //fresh every iteration
    $personalizedCertificate = str_replace("&lt;&lt;name&gt;&gt;", $fullNames[0], $personalizedCertificate);

    $mpdf->WriteHTML($personalizedCertificate);
    $mpdf->Output($serverPathCertificate);

    //gc_collect_cycles();
}
finwe commented 1 year ago

Generating PDFs in a loop [with a single instance] is generally not recommended. Create and clear a separate mPDF instance for each generated document.

finwe commented 1 year ago

That meaning, current behavior will most likely not be changed as it is not worth the time needed.

marhyno commented 1 year ago

got it, thank you