Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

tcpdf or similar

edited March 2013 in Apps

Anyone tried producing "Save page as pdf" links using tcpdf or other libraries?


  • I have this working, kind of. I adapted my property view to call tcpdf. I'm capturing the output of $tpl->render and passing it to tcpdf. However, $tpl->render only gets {{ body }} and I'd prefer to send the whole page to tcpdf. How do I do that?

  • edited March 2013

    I would look at the render() function of that for clues. Not near a computer right now so I can't give too detailed of an analysis.

    Perhaps $pdf_text = $page->render()? (Random stab, you may need params on that)

  • There are two ways you could go about this:

    The first would be to grab the HTML from the current page via JavaScript and POST it to a new request. You don't have to duplicate the old request that way, and the new handler can just take a $_POST['html'] parameter and send that to tcpdf. For example:

    function save_as_pdf () {
        var form = $('<form>')
            .attr ('method', 'post')
            .attr ('action', '/tcpdf/render');
            .attr ('type', 'hidden')
            .attr ('name', 'html')
            .attr ('value', document.documentElement.innerHTML)
            .appendTo (form);
        form.appendTo ('body');
        form.submit ();
        return false;
    <a href="#" onclick="return print_to_pdf ()">Save page as PDF</a>

    And in PHP:

    <?php // apps/tcpdf/handlers/render.php
    $page->layout = false;
    $html = $_POST['html'];
    // now pass $html to tcpdf

    A second way would be to proxy the request through a secondary script, similar to how the subfolder proxy works. Something like this:

    <?php // saveaspdf.php
    $_SERVER['REQUEST_URI'] = $_GET['uri'];
    ob_start ();
    require_once ('index.php');
    $html = ob_get_clean ();
    // now pass $html to tcpdf

    And the link becomes:

    <a href="/saveaspdf.php?uri={{$_SERVER.REQUEST_URI|urlencode}}">Save page as PDF</a>

    The advantage of the first is skipping re-rendering the same page over again on the server, but the second may be more secure since the first will also convert any arbitrary HTML posted to /tcpdf/render.

  • Thanks for the help. I am having some issues with tcpdf and paths but I will fiddle with it some more when I get a chance.

  • I have this working, kind of. tcpdf apparently doesn't support external stylesheets, so I switched to dompdf. I still had some problem with paths, but prepending $_SERVER["DOCUMENT_ROOT"] to every path seems to fix it.

    However, dompdf doesn't do floats well, so the embedded image gallery doesn't work well. I think I will need to set up a different view for the pdfs and pass that url to saveaspdf.php.

  • My browser gives an error with the rendered pdf unless I have compress_output = Off in conf/config.php. Is it possible to turn that off from the handler instead of globally?

  • You can turn it off for the current request like this:

    conf ('General', 'compress_output', false);
  • This is on a page based on your saveaspdf.php above, which I don't think is part of the normal elefant environment.

  • How about this then:

    Define a constant at the top of your saveaspdf.php:

    define ('SAVING_AS_PDF', 1);

    Then create a handler in Elefant like this:

    if (defined ('SAVING_AS_PDF')) {
        conf ('General', 'compress_output', false);

    Then include this handler in your layout template via a {! myapp/pdfconfig !}. That should cause it to automatically disable it for any request that's routed through your safeaspdf.php script.

  • Still no luck.

    The URL is "/pdf.php?uri=homes/beautiful-log-home"

    Here's my pdf.php:

    $_SERVER['REQUEST_URI'] = $_GET['uri'];
    define ('SAVING_AS_PDF', 1);
    ob_start ();
    require_once ('index.php');
    $html = ob_get_clean ();
    $html = str_replace ('"/css/', '"'.$_SERVER["DOCUMENT_ROOT"].'/css/', $html);
    $html = str_replace ('"/files/', '"'.$_SERVER["DOCUMENT_ROOT"].'/files/', $html);
    $html = str_replace ('"/apps/', '"'.$_SERVER["DOCUMENT_ROOT"].'/apps/', $html);
    $html = str_replace ('"/js/', '"'.$_SERVER["DOCUMENT_ROOT"].'/js/', $html);
    $html = str_replace ('"/cache/', '"'.$_SERVER["DOCUMENT_ROOT"].'/cache/', $html);
    $title = urldecode (Property::name_only ($_GET['uri']));
    $dompdf = new DOMPDF();
    $dompdf->set_paper ('letter', 'landscape');
    // $dompdf->set_base_path ($_SERVER["DOCUMENT_ROOT"]);  // seems to have no effect
    $dompdf->stream("$title.pdf", array("compress" => 0, "Attachment" => 0));

    Page 'homes' calls 'properties/index?type=Homes'

    Here is the relevant part of apps/properties/handlers/index.php:

    if (defined ('SAVING_AS_PDF')) {
        conf ('General', 'compress_output', false);
        $page->layout = 'pdf';
        echo $tpl->render (
    } else {

    Here is the header output according to firefox live headers:

    HTTP/1.1 200 OK
    Date: Fri, 08 Mar 2013 16:13:54 GMT
    Server: Apache/2.2.22 (Ubuntu)
    X-Powered-By: PHP/5.3.10-1ubuntu3.5
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: private
    Pragma: no-cache
    Content-Encoding: gzip
    Vary: Accept-Encoding
    Content-Length: 162896
    Content-Disposition: inline; filename="beautiful-log-home.pdf"
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Content-Type: application/pdf

    Here is the error in firefox:

    Content Encoding Error
          The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
     Please contact the website owners to inform them of this problem.

    If I set compress_output = Off in conf/config.php the pdf output works fine.

  • Ah this is stupid of me. The conf() function wasn't setting a value if the 3rd value was false, so that's why it wasn't working. It now properly checks, so the code should work with my last commit.

  • It works! :)

Sign In or Register to comment.