简体   繁体   中英

CakePHP 3 CakePDF Plugin: Generating a large PDF by looping through content?

So my problems stems from trying to generate large PDF files but being hit by the memory limit / execution timeouts in PHP, the data is too great in volume to simply extend these limits so that solution is out of the question.

I have a background shell task running which handles all of this rendering and then alerts the user once the PDF has been completed.

In theory I would have a loop within this shell which would take in a chunk of data and render it to file, then take the next chunk and do the same. Once out of data to render, the file would then be written and completed ready to be served. This way the memory limit of PHP would not be hit as a manageable chunk will only ever be loaded.

I am currently using the CakePDF(v.3.5) plugin for CakePHP 3 (v.3.5.13) but am sturggling to find a solution which allows the rendering of some data and then adding more data to the same pdf. Has anyone managed this before or is it out of scope of the plugin? Would another solution be to create multiple PDF files and then merge them together after all separate PDF's have been created?

This is more of a theoretical question if this would work and if anyone has managed it before. I don't have much code to show but if more detail is required then give me a shout and I will try and get something for you or some example code!

Thanks

That's certainly out of the scope of the plugin, it's built around the idea of rendering a single view to a single file, the interface doesn't support chunked creation of a single file, and if I'm not mistaken, none of the supported engines do support that either, at least not in a straightforward and efficient manner when it comes to large documents.

There's certainly lots of ways to do this, creating multiple PDFs and merging/concatenating them afterwards might be one of them, generating the source content in chunks, and passing it to a PDF renderer that can handle lots of content efficiently might be another one, and surely there also might be libraries out there that do explicitly support chunked creation of PDFs...

I don't have direct experience with that version CakePdf, but under CakePHP 2.x I use the wkhtmltopdf engine which takes an .html output to produce the PDF.

If your shell generates such .html in chunks, it is easy to append. Of course wkhtmltopdf is likely to put some load on the machine to produce the PDF, but since it's a binary, it happens outside of PHP's memory/time contraints.

I thought I would post what I ended up doing for anyone in the future.

I used CakePDF to generate smaller PDF's which I stored in a tmp directory these are all under the limit of PHP's execution time and memory limits as I don't believe altering those provides a good solution. In this step I also saved the names of all of the PDF's generated for use in the next step. The code for this looked something like:

while (!is_last_pdf) {
    // Generate pdf in here with a portion of the data
    $CakePdf = new CakePdf();
    $CakePdf->template('page', 'default');
    $CakePdf->viewVars(compact('data', 'other_stuff'));

    // Save file name to array
    $tmp_file_list[] = $file_name;

    // Update the is_last_pdf variable 
    is_last_pdf = check_for_more_data();
}

From this I used GhostScript from within the Shell to merge all of the PDF files, the code for this looked something like this:

$output_path = 'output.pdf';
$file_list = '';

// Create a string of all the files to merge
foreach ($tmp_file_list as $file) {
    $file_list .= $file . ' ';
}

// Execute GhostScript to merge all the files into the `output.pdf` file
exec('gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=' . $output_path . ' ' . $file_list);

All of the code here was in the Shell file responsible for creating the PDF.

Hope this helps someone :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM