Flask x-html2pdf with images

Flask x-html2pdf with images

There is a problem when generate pdf with images using xhtml2pdf library. It took me quite some time to resolve these issues.

I’m using flask, microframework to generate the pdf. The first issues was the library dependency, it required to specified with version

html5lib==1.0b8

Next,  issues

No handlers could be found for logger “xhtml2pdf”

This can be easily add the following code to find the real problem by adding this code

import logging
pisa.showLogging()

Complete example

from xhtml2pdf import pisa
from StringIO import StringIO
import logging
pisa.showLogging()

def create_pdf(pdf_data):
    pdf = StringIO()
    pisa.CreatePDF(StringIO(pdf_data.encode('utf-8')), pdf)
    resp = pdf.getvalue()
    pdf.close()
    return resp

After that you shall see something more useful error message like below

WARNING [xhtml2pdf] /workspace/merchant/venv/lib/python2.7/site-packages/xhtml2pdf/tags.py line 408: Need a valid file name!
u'<img class="logo-center" src="/static/logo.png" style="zoom: 40%;"/>'

Next, the pdf generated contains no images. My images files was placed in /app/static/images/maillogo.png

<img src="{{ url_for('static', filename='images/maillogo.png') }}" />

The easier solution is to place the images together with the html file.

<img src="maillogo.png" height="60" width="120"/>

Run again directly compile with the command:

(venv) workspace mingch$ xhtml2pdf app/templates/mail/vourcher.html 
Converting app/templates/mail/vourcher.html to /workspace/app/templates/mail/vourcher.pdf...

But when you run in server mode, the problem is still persist. The root cause were suspect xhtml2pdf is not able to read the relative path. If you check on the this link, the error was cause by attr.src and (not attractive.src.notFound()):

class pisaTagIMG(pisaTag):

    def start(self, c):
        attr = self.attr
        if attr.src and (not attr.src.notFound()):
            try:
                align = attr.align or c.frag.vAlign or "baseline"
                # print "align", align, attr.align, c.frag.vAlign

Therefore, one possible solution is pass the absolute path as parameters.

Step 1: Get the absolute images path and assign into a variable

image_logo = os.path.join(os.getcwd(), 'app/static/images', 'maillogo' + '.png')

Step 2: Pass the variable into the template

vourcher = create_pdf(render_template('mail/vourcher.html',
                                        image_logo=image_logo))

One comment

  1. IT WORKS PERFECTLY!!! THANKS A LOT!!!

    Reply

Write a Reply or Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.