WkHTMLtoPDF not loading local CSS and images

HtmlWkhtmltopdf

Html Problem Overview


I've seen multiple questions that are very similar to this one, so I was hesitant at first to post it. But nothing suggested resolved my issue and I can't seem to figure out what's wrong myself.

For a project I made for one client they wanted to ability to convert quotes for their customers (generated using an online form) to PDFs. Simple enough. As the entire project was in PHP, I used the following simple process:

  1. Save the quote as a temporary HTML file
  2. Use WkHTMLtoPDF to convert the HTML file to a PDF
  3. Output this PDF file
  4. Clean up (delete temporary files)

This worked until they changed servers. The new server has a firewall.

At first the PDF conversion step was returning a firewall page saying that the server couldn't make outbound connections. To resolve this I fed the HTML file directly instead of linking to it (/var/www/mysite/temp/18382.html instead of www.example.com/temp/18382.html). This converted the HTML, but the firewall prevented the loading of CSS and images

I can overcome the CSS by simply embedding it directly in the site instead of linking to it (using the <style> tags), but this doesn't work for images

I tried using relative links first. I changed <img src="http://www.example.com/temp/image.jpg" /> to <img src="./image.jpg" />. This didn't work.

Next I tried <img src="file:///var/www/mysite/temp/image.jpg" /> but this didn't work, either

I read around and look through the WkHTMLtoPDF manual and I tried several different command line arguments like --enable-local-file-access, --enable /var/www/mysite/temp/, and --images but nothing seems to fix it

Html Solutions


Solution 1 - Html

In my case - wkhtmltopdf version 0.12.2.1 (with patched qt) - adding a base tag to the head section with the absolute path made sure images and css did get loaded.

<html>
<head>
...
<base href="http://www.example.com/">
<link href="/assets/css/style.css" rel="stylesheet">
...
</head>

Solution 2 - Html

If your are on linux check the ownership of your images. For windows you will find some info on http://code.google.com/p/wkhtmltopdf/wiki/Usage.

I tried different kind of paths to the image:

  1. <img src="file:///var/www/testpdf/flowers.jpg"><br>
  2. <img src="./flowers.jpg"><br>
  3. <img src="flowers.jpg"><br>
  4. <img src="/var/www/testpdf/flowers.jpg"><br>

all images are showed correct. I didn't use any command line arguments (only wkhtmltopdf /var/www/testpdf/makepdf.html makepdf.pdf)

Solution 3 - Html

For Windows you need to use absolute file system paths in your markup. For instance:

<link href='C:\Projects\Hello\Hello.Web\Content\custom\home.css' rel='stylesheet' type='text/css' />

! not http://localhost/Hello.Web/Content/custom/home.css

Solution 4 - Html

In order to have them embed, you can insert base64 encoded images like :

<img src="data:image/png;base64,someBase64content"/>

Solution 5 - Html

When a browser renders your HTML, it uses a relative path (sometimes with a URL at the beginning of it) like this:

<img src="/static/images/some_picture.png">
<img src="http://www.example.com/static/images/some_picture.png">

But when WkHTMLtoPDF is running on your server, it's interfacing with your local files directly through the filesystem, not through a web server. So for local files, unlike a browser, WkHTMLtoPDF wants the actual filepath:

<img src="/var/www/myapplication/static/images/some_picture.png">

(This worked for me with Python Flask)

Solution 6 - Html

on Windows use path: file:///C:/some/dir/some/file.img (notice the tripple /)

Solution 7 - Html

After taking in everyone's kind assistance from here and around the net, I discovered something that worked for me - coding in asp.net (c#).

I needed to access the image by url (not file path), as the original source html still needed to be accessed. Through troubleshooting, I discovered these points.

  1. These flags had to be passed in to the command line process: "-q -n --disable-smart-shrinking --images --page-size A4"

  2. URL still has to be absolute.

  3. Image must be a jpg! I was originally trying to do a gif, to no avail.

  4. I discovered adding "--enable-local-file-access" didn't help, as it requires '' slashes in the image path instead of '/' slashes, which doesn't help if you also hope to use the source html (in some browsers). Also, if you need to access the local file system, you need to provide an absolute path, as it reads straight from the root and goes from there.

Hope this helps others.

Cheers

-y

Solution 8 - Html

I know this is quite old topic, but I've just faced the same issue and maybe it will help to someone.
I tried different approaches, like css background image and using string as base64 encoded data image. Sometimes it helped, sometimes not - no particular rule I could found.
It turned out that upgrading library wkhtmltopdf solved the problem. I was using version 0.12.0 and upgraded to 0.12.3

Solution 9 - Html

What fixed it for me was removing the references to my CSS files. It turned out I had was setting img { max-height: 100%; } in an otherwise-empty div so that was being interpreted as max-height: 0.

So check out your CSS and there might an issue there. This worked:

<div><img src="image.png"/></div>

And running command line in the directory with image.png:

wkhtmltopdf example.html example.pdf

But this does not:

<div><img src="image.png" style = "max-height: 100%; "/></div>

Because the image gets squished to 0 height. Firefox seems to correct this so it wasn't obvious.

Solution 10 - Html

make sure you have the latest version of wkhtmltopdf with patched qt.
you can implement a helper that flask jinja uses it to distinguish if the template is for rendering or only generating pdf, or maybe both.
let' say that tmpl_bind is the data object to bind in the template, add a new key tmpl_bind["pdf"] set it True or False.
when using wkhtmltopdf or pdfkit, add enable-local-file-access to options object.
now create a helper function called static_file

def static_file(filename, pdf=False):
    # wkhtmltopdf only read absolute path
    if pdf:
        basedir = os.path.abspath(app.root_path)
        return "".join([basedir, "/static/", filename])
    else:
        return url_for('static', filename = filename)  

as we say, wkhtmltopdf for some os only read files when you include their absolute path. Note that you may add or remove parts from the app.root_path, according to your app structure, but this will work in most of cases.

in app configuration add this line after importing static_file function if it is in another file

app.jinja_env.globals['static'] = static_file

finally, in the template import files, images by calling the static_file helper function

<link href="{{ static('css/style.css', pdf) }}" rel="stylesheet" />
<img src="{{ static('assets/images/logo.svg', pdf) }}" class="logo"> 

Solution 11 - Html

It is may be too late :)

BTW, just add this config into your options in last.

options = {'enable-local-file-access': None}
pdfkit.from_string(html, 'filename.pdf', options=options)

Solution 12 - Html

Just spent a few days on getting a Flask/ Blueprint /static file/ css to be read by wkhtmltopdf, so I thought I'd share what I learned. Win 7, Flask 0.12 on Python 3.4.4, using Pycharm pro, latest pdfkit and wkhtmltopdf.

  1. download the wkhtmltopdf here

  2. install it -mine installed on:

    C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe

  3. right after you import pdfkit into your flask routes.py script ,insert the lines:

    path_wkthmltopdf = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'

    config = pdfkit.configuration(wkhtmltopdf=path_wkthmltopdf)

(note the "r" in the first line here !! )

  1. when you use pdfkit in a route, add ",configuration = config" as an argument, eg:

    pdfkit.from_string(html_text, output_filename, configuration = config)

this tells pdfkit where to look for wkhtmltopdf. Yes, you need to do this.

  1. NOW in your flask BASE TEMPLATE add , _external = True to your css route, eg:

(this will keep wkhtmltopdf from throwing error cant find css)

  1. NOW (serious bootstrap template juju warning): go into your flask /external libraries /site-packages /flask_bootstrap /templates /base.html template and:

a. fix CSS link:

<link href="{{bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap')}}" rel="stylesheet" media="screen">

add "http:" so it looks like:

<link href="http:{{bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap')}}" rel="stylesheet" media="screen">

b. fix JS links:

add "http:" so the JS links look like:

<script src="http:{{bootstrap_find_resource('jquery.js', cdn='jquery')}}"></script>

<script src="http:{{bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap')}}"></script>

and with all this

your flask html to pdf conversion

using pdfkit and wkhtmltopdf

should run without errors.

note: I moved to flask from PHP and if you are a flask-er, please post your solutions up here. The flask community is MUCH smaller than the PHP community so we all have to pitch in.

Solution 13 - Html

For me the problem was resolved by doing two things:

1: In your app/config/config.yml

  • Under the knp_snappy
  • For the option temporary_folder write ./
  • i.e: temporary_folder: ./

2: Now in your html.twig pages remove the asset and write:
From:

 <link rel="stylesheet" type="text/css" href="{{ asset('css/default_template.css') }}">
To:
 <link rel="stylesheet" type="text/css" href="css/default_template.css">

And after that, it worked for me.

Hopefully i've helped somebody. Thank you !

Solution 14 - Html

This is probably due to SE Linux or firewall rules that prevent you from going out on the internet and back to your own server. You can update your host file to point calls to your domain back to your machine's home address.

Solution 15 - Html

To generate your pdf with your images or styles you need to provide the server path as follows:

<img src="https://upload.wikimedia.org/wikipedia/...image.png" />

<link href="http://localhost:8080/css/file.css" media="all" rel="stylesheet" type="text/css" />

Note this second link, it's the local address to your stylesheet, or could be a remote like the first link. The file path didn't work for me, only the server path to the resource.

Ps: In my situation, I am using spring boot in Intellij IDE and I needed to invalidate cache of IDE and not run in debug mode in order to work, otherwise it may be not update things.

Solution 16 - Html

URL of images must be absolute not relative. Check this working example in a twig template:

<img src="{{ absolute_url(asset('images/example.png')) }}"/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstevendesuView Question on Stackoverflow
Solution 1 - Html10usView Answer on Stackoverflow
Solution 2 - HtmlBass JobsenView Answer on Stackoverflow
Solution 3 - HtmlvladimirView Answer on Stackoverflow
Solution 4 - HtmlYemMView Answer on Stackoverflow
Solution 5 - HtmlJoshView Answer on Stackoverflow
Solution 6 - HtmlparanoiqView Answer on Stackoverflow
Solution 7 - HtmlYvesView Answer on Stackoverflow
Solution 8 - HtmlwladimirecView Answer on Stackoverflow
Solution 9 - HtmlBryce ChamberlainView Answer on Stackoverflow
Solution 10 - Htmlalim91View Answer on Stackoverflow
Solution 11 - HtmlsumiyaView Answer on Stackoverflow
Solution 12 - HtmlpelonView Answer on Stackoverflow
Solution 13 - HtmlTiescoView Answer on Stackoverflow
Solution 14 - HtmlE WView Answer on Stackoverflow
Solution 15 - HtmlGuilherme AlencarView Answer on Stackoverflow
Solution 16 - HtmlnumediawebView Answer on Stackoverflow