8

I am using PDFkit with python to convert an html page to pdf. In the html there is only one image tag in body with src pointing to a complete url like:

<html>
    <body style="margin: 0px;">
        <img style="-webkit-user-select: none; cursor: -webkit-zoom-in;" src="https://blah.blah.com" height="768">
    </body>
</html>

However When I convert html to pdf like this:

pdfkit.from_file(file, 'labels.pdf', configuration=config)

I get a blank page with a box with border instead of image.

Why is pdfkit not converting image?

I read somewhere that we have to give full image path including domain name. But the image url I am providing is complete. Then what I am doing wrong?

Manish Gupta
  • 4,438
  • 18
  • 57
  • 104
  • I quickly tested this and got pdf with image. See if this works without passing configuration `pdfkit.from_file(file, 'labels.pdf')`. If it does, there's something wrong with your configuration. May be you are using configuration instead of options? –  Jul 12 '16 at 13:24

6 Answers6

10

I encoded the image as a string of Base64 data, following @Manish Gupta's suggestion. In Python:

import base64

def get_image_file_as_base64_data():
    with open(FILEPATH, 'rb') as image_file:
        return base64.b64encode(image_file.read())

In my Jinja2 template (I know the question isn't specific to Jinja2, but this is what I'm using):

<img src="data:;base64,{{ get_image_file_as_base64_data() }}">
Josh
  • 2,790
  • 26
  • 30
4

I use the file path instead of the file url in image src, like:

<img src="D:/image/path/pircure.png">

and it work, maybe you can try it.

Adrian Lin
  • 41
  • 2
3

I liked the approach of Adrian Lin. Though, I am using Django in Docker and the following is working for me just great:

Python:

from django.template import Context, Template
import pdfkit

template_folder = 'media'
context['media_folder'] = os.path.abspath(template_folder)

template_file = os.path.join(template_folder, 'template.html')
with open( template_file, 'r') as f:
    template = Template(f.read())

html_file = template.render(Context(context))

pdfkit.from_string(html, filename)

Html template:

<img src="{{media_folder}}/my_pic.png">
Egor Wexler
  • 1,754
  • 6
  • 22
2

These other answers weren't working for me, but I was able to piece a few answers together from here and other sources and found this solution.

I have a jinja template with the tag:

<img src="data:image/png;base64,{{ img_string }}" width="500px">

Then, I pass the template an image as a base64 encoded string by running it through the following function:

def image_file_path_to_base64_string(filepath: str) -> str:
  '''
  Takes a filepath and converts the image saved there to its base64 encoding,
  then decodes that into a string.
  '''
  with open(filepath, 'rb') as f:
    return base64.b64encode(f.read()).decode()

So in the end, ignoring sundry Jinja initializations I have

# generate html with base64 encoded string of image
html_string = jinja_template.render(
    img_string=image_file_path_to_base64_string('path/to/img.png'))

# generate pdf
pdfkit.from_string(html_string, 'html.pdf')

0

I have solved it in a slightly similar way and it smoothly converts the image.

in views:

pdf_content = pdfkit.from_string(html_string, False)

In template tags:

@register.filter
def get_image_file_as_base64_data(CONTRACTOR_LOGO):
    image_bytes = CONTRACTOR_LOGO.read()
    base64_bytes = base64.b64encode(image_bytes)
    base64_string = base64_bytes.decode("ascii")
    return base64_string

in template file

<img style="height: 35px;" alt="Contractor Logo" src="data:image/png;base64, {{ contractor.logo | get_image_file_as_base64_data }}">

Note: Here I am sending the image file to the template tag which processes the image and returns base64_string.

0

I'm using flask + Jinja2 and the best solution I found is passing the media folder as parameter based on current_app.config.root_path:

In Python code:

...
rendered_template = render_template(template_path, **data, media_folder=str(Path(current_app.config.root_path)/'static'))
...

In HTML:

<img src="{{media_folder}}/img/file_name.png">
Nadhem Maaloul
  • 433
  • 5
  • 11