Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

generating a PDF from HTML takes a long time only when using local assets

I use KnpSnappyBundle 1.6.0 and wkhtmltopdf 0.12.5 to generate PDFs from HTML in PHP like so:

$html = $this->renderView(
    'pdf/template.html.twig',
    [ 'entity' => $entity, ]
);

return new PdfResponse($snappy->getOutputFromHtml($html,
    ['encoding' => 'UTF-8', 'images' => true]), 'file'.$entity->getUniqueNumber().'.pdf'
);

My issue: on my production server, when I refer to assets (images or css) that are hosted on the same server as my code, generating a PDF takes around 40-50 seconds. Even when I only use a tiny image that is hosted on the same server it takes 40 seconds. I could use images that are much larger that are hosted on another server and generating the PDF will happen instantly.

My server is not slow in serving assets or files in general. If I simply render out the HTML as a page it happens instantly (with or without the assets). When I locally (on my laptop) request assets from my production server to generate a PDF it also happens instantly.

The assets I require in the HTML that needs to be rendered to PDF all have absolute URLs, this is required for wkhtmltopdf to work. For example: <img src="https://www.example.com/images/logo.png"> The difficult thing is, everything works but just very slowly. There is no pointing to a non-existent asset that would cause a time-out.

I first thought it might have to do with wkhtmltopdf, so I tried different versions and different settings, but this did not change anything. I also tried to point to another domain on the same server, the problem remains. I tried not using the KnpSnappyBundle, but the problem also remains.

So my guess now is that it is a server issue (or a combination with wkhtmltopdf). I am running Nginx-1.16.1 and serve all content over SSL. I have OpenSSL 1.1.1d 10 Sep 2019 (Library: OpenSSL 1.1.1g 21 Apr 2020) installed and my OS is Ubuntu 18.04.3 LTS. Everything else works as expected on this server.

When I look in the Nginx access logs, I can see a get request is made by my own IP-address when using assets from the same server. I cannot understand though why this is taking so long and I have run out of ideas of what to try next. Any ideas are appreciated!

I'll add my Nginx config for my domain (in case it might help):

server {
        root /var/www/dev.example.com/public;
        index index.php index.html index.htm index.nginx-debian.html;

        server_name dev.example.com www.dev.example.com;

        location / {
        # try to serve file directly, fallback to index.php
        try_files $uri /index.php$is_args$args;     
    }

        location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        internal;
    }

  location ~ \.(?:jpg|jpeg|gif|png|ico|woff2|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|js|css)$ {
        gzip_static on;

        # Set rules only if the file actually exists.
        if (-f $request_filename) {
        expires max;
        access_log off; 
        add_header Cache-Control "public";
    }
            try_files $uri /index.php$is_args$args;     
 }

    error_log /var/log/nginx/dev_example_com_error.log;
    access_log /var/log/nginx/dev_example_com_access.log;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = dev.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name dev.example.com www.dev.example.com;
    listen 80;
    return 404; # managed by Certbot
}

Udate 5 Aug 2020: I tried wkhtmltopdf 0.12.6, but this gives me the exact same problem. The "solution" that I posted as an answer to my question a few months ago is far from perfect which is why I am looking for new suggestions. Any help is appreciated.

like image 395
Dirk J. Faber Avatar asked Nov 04 '19 10:11

Dirk J. Faber


People also ask

Which is the best PDF library for PHP?

MPDF is an HTML-to-PDF generator based on FPDF, one of the original PHP PDF conversion libraries. It has excellent documentation. Unfortunately, it also lacks support for JavaScript and is slow, especially with large tables. MPDF has added support for custom HTML tags to improve page break and header handling.

How do I create a PDF from a web application?

To create a PDF from the currently open web page, choose Convert Web Page To PDF. Then select a location, type a filename, and click Save. To add a PDF of the currently open web page to another PDF, choose Add Web Page To Existing PDF. Then locate and select the existing PDF, and click Save.


1 Answers

This sounds like a DNS issue to me. I would try adding an entry in /etc/hosts for example:

127.0.0.1     example.com
127.0.0.1     www.example.com

And pointing your images to use that domain

like image 170
kaan_a Avatar answered Nov 15 '22 09:11

kaan_a