WkHTMLtoPDF not loading local CSS and images
Asked Answered
I

18

70

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

Incumber answered 18/5, 2013 at 17:56 Comment(6)
Have you had a look at the firewall logs? That might help you identify the actual issue. Local file access is not affected by a firewall.Bullis
@Bullis I'm aware local access isn't affected by a firewall, but I suspect it's either not supported by wkhtmltopdf or I'm not implementing it correctly. I'll check the logs right now to see if it was using HTTP when I requested the file locallyIncumber
@Bullis Just checked, nothing. It's requesting locally but failing to loadIncumber
Have a look at this then. I don't know the package. I could have helped if it was actually a firewall thingy.Bullis
if your are on linux check the ownership of your images. For windows you will find some info on code.google.com/p/wkhtmltopdf/wiki/Usage. I tried: 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)Supernatant
@BassJobsen Oh my god, that was it! WkHTMLtoPDF is running on its own user but the images are owned by the Apache user. I put chown just before the call to WkHTMLtoPDF and suddenly it's working. Please post this as an answer so I can accept it =)Incumber
S
31

If you're 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">
  2. <img src="./flowers.jpg">
  3. <img src="flowers.jpg">
  4. <img src="/var/www/testpdf/flowers.jpg">

All images are shown correctly. I didn't use any command line arguments (only wkhtmltopdf /var/www/testpdf/makepdf.html makepdf.pdf)

Supernatant answered 20/5, 2013 at 13:30 Comment(7)
hei, why this answer be voted? I haven't found any solution to your question? Now i'm facing the same problem, image can't be captured in pdf, but show well in browser.Anzio
Solution #4 worked for me. If you use linux console just write the command "pwd" to get the current server path.Auto
The only one that works for me is #1 : file:///var/www/path/to/my/project/and/assets/flowers.jpgStepup
It's been years since I had this issue and I couldn't say specifically why I chose this answer, but my guess is that upon inspecting the permissions I found the file ownership was wrong.Incumber
Using #1 also worked for me when trying to generate a PDF with a lot of images (+-150).Siana
2nd and 3rd options didn't work on both linux and windows.Eucalyptus
this helped me figure out how to solve my problem. had related problem with "how to load custom font in css file" and this tells you quite a bit src: url("./proxima-bold.otf") format("opentype");Indemnify
M
53

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>
Middleclass answered 18/4, 2016 at 13:45 Comment(2)
This definitely works. enable-local-file-access did not do anything. Or you can simply do <link href="http://www.example.com/assets/css/style.css" rel="stylesheet"> without base tag.Rental
even I have base tag given, html page render perfect but pdf don't consider cssHashimoto
S
31

If you're 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">
  2. <img src="./flowers.jpg">
  3. <img src="flowers.jpg">
  4. <img src="/var/www/testpdf/flowers.jpg">

All images are shown correctly. I didn't use any command line arguments (only wkhtmltopdf /var/www/testpdf/makepdf.html makepdf.pdf)

Supernatant answered 20/5, 2013 at 13:30 Comment(7)
hei, why this answer be voted? I haven't found any solution to your question? Now i'm facing the same problem, image can't be captured in pdf, but show well in browser.Anzio
Solution #4 worked for me. If you use linux console just write the command "pwd" to get the current server path.Auto
The only one that works for me is #1 : file:///var/www/path/to/my/project/and/assets/flowers.jpgStepup
It's been years since I had this issue and I couldn't say specifically why I chose this answer, but my guess is that upon inspecting the permissions I found the file ownership was wrong.Incumber
Using #1 also worked for me when trying to generate a PDF with a lot of images (+-150).Siana
2nd and 3rd options didn't work on both linux and windows.Eucalyptus
this helped me figure out how to solve my problem. had related problem with "how to load custom font in css file" and this tells you quite a bit src: url("./proxima-bold.otf") format("opentype");Indemnify
R
21

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

Retrograde answered 3/12, 2013 at 17:28 Comment(4)
Latest version work for me with a local setup (i.e. localhost/Hello.Web/Content/custom/home.css) They may have fixed this. Though relative paths were still not working for me on windows.Eisler
I use this lib (old version, without namespaces) in Yii2, and link worked for me too:<?= Html::img(Url::to('@web/images/settlement-raports/label.png', true)); ?>, where to() method returns http://mp.local/images/settlement-raports/label.png.Nipper
This worked for me. The images weren't rendering properly, and now they finally are.Ardithardme
This may help Razor / cshtml developers to avoid hard-coding the absolute path: <link href="@($"file:///{System.IO.Directory.GetCurrentDirectory()}\\style.css")" rel="stylesheet" type="text/css" />Malmsey
S
21

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

<img src="data:image/png;base64,someBase64content"/>
Semiquaver answered 5/4, 2018 at 14:32 Comment(1)
There is a " missing at the beginning of src.Marchak
B
11

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)

Betide answered 28/2, 2018 at 1:10 Comment(0)
M
8

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)
Mandel answered 17/8, 2021 at 6:35 Comment(0)
E
5

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

Ethelstan answered 14/10, 2014 at 16:18 Comment(0)
C
3

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

Cultus answered 19/5, 2014 at 0:49 Comment(0)
S
3

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

Situated answered 18/2, 2016 at 12:57 Comment(3)
What was your process for upgrading to 0.12.3?Impediment
@Impediment Upgrade has been made just by replacing binaries. However I'm afraid my judgment was too quick. It doesn't solve the problem at all, but it happens less frequently I think. General problem is when I'm trying to generate PDF from multiple input html files. The only solution I found so far is to convert every input HTML one by one and finally merge them into single PDF using some other library.Situated
OK, finally it turned out the problem was related to OS somehow. For me problem occurs on ubuntu 10.04, but it has never happen again after upgrade to 12.04.Situated
M
3

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.

Methyl answered 20/11, 2019 at 21:15 Comment(0)
S
3

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"> 
Snelling answered 17/12, 2020 at 10:30 Comment(0)
F
2

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!)

  4. 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.

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

    <link rel="stylesheet" type = "text/css"
       href="{{url_for(('.static'), filename = ('your_sheet.css'), _external=True ) }}" >
    

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

  6. 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.

Fabrianne answered 5/3, 2017 at 20:4 Comment(0)
B
2

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.

Battled answered 24/1, 2018 at 0:2 Comment(0)
B
1
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 !

Bine answered 17/8, 2017 at 8:21 Comment(0)
G
1

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.

Gagliano answered 8/4, 2019 at 20:23 Comment(0)
M
1

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

<img src="{{ absolute_url(asset('images/example.png')) }}"/>
Motorcade answered 10/7, 2019 at 9:54 Comment(0)
M
1
opt = dict()
opt["orientation"] = "landscape"
opt["enable-local-file-access"] = ""
config = pdfkit.configuration(wkhtmltopdf='/usr/bin/wkhtmltopdf')

enable local file access to access images

Mauk answered 14/2, 2023 at 8:42 Comment(0)
H
0

If you use WickedPdf you might want to use:

WickedPdf.config = { enable_local_file_access: true }

And use absolute path, you can use any type of image (e.g. svg, jpg, png)

Holiness answered 11/9, 2023 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.