pdfkit headers and footers

13,697

Solution 1

I'm using it only with headers but I think that it will work the same with footers.

You need to have separate html file for the header.

header.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>

    Code of your header goes here.

</body>
</html>

Then you can use it like that in Python

import pdfkit

pdfkit.from_file('path/to/your/file.html', 'out.pdf', {
    '--header-html': 'path/to/header.html'
})

The tricky part if you use some backend like Django and want to use templates is that you can't pass the header html as rendered string. You need to have a file.

This is what I do to render PDFs with Django.

import os
import tempfile
import pdfkit

from django.template.loader import render_to_string


def render_pdf(template, context, output, header_template=None):
    """
    Simple function for easy printing of pdfs from django templates

    Header template can also be set
    """
    html = render_to_string(template, context)
    options = {
        '--load-error-handling': 'skip',
    }
    try:
        if header_template:
            with tempfile.NamedTemporaryFile(suffix='.html', delete=False) as header_html:
                options['header-html'] = header_html.name
                header_html.write(render_to_string(header_template, context).encode('utf-8'))

        return pdfkit.from_string(html, output, options=options)
    finally:
        # Ensure temporary file is deleted after finishing work
        if header_template:
            os.remove(options['header-html'])

In my example I create temporary file where I put rendered content. Important part is that temporary file need to end with .html and to be deleted manually.

Solution 2

Improving @V Stoykov answer as it helped me using Flask, the render function with custom header in Flask will be as follows:

import os
import tempfile

import pdfkit
from flask import render_template, make_response


@app.route('/generate_pdf')
def render_pdf_custom_header(foo, bar):
    main_content = render_template('main_pdf.html', foo=foo)
    options = {
        '--encoding': "utf-8"
    }

    add_pdf_header(options, bar)
    add_pdf_footer(options)

    try:
        pdf = pdfkit.from_string(main_content, False, options=options)
    finally:
        os.remove(options['--header-html'])
        os.remove(options['--footer-html'])

    response = build_response(pdf)
    return response

def add_pdf_header(options, bar):
    with tempfile.NamedTemporaryFile(suffix='.html', delete=False) as header:
        options['--header-html'] = header.name
        header.write(
            render_template('header.html', bar=bar).encode('utf-8')
        )
    return

def add_pdf_footer(options):
    # same behaviour as add_pdf_header but without passing any variable
    return

def build_response(pdf):
    response = make_response(pdf)
    response.headers['Content-Type'] = 'application/pdf'
    filename = 'pdf-from-html.pdf'
    response.headers['Content-Disposition'] = ('attachment; filename=' + filename)
    return response

Notice that I used the '--header-html' and '--footer-html' notation as it matches the wkhtmltopdf options format.

Solution 3

options = {
'page-size': 'Letter',
'margin-top': '0.9in',
'margin-right': '0.9in',
'margin-bottom': '0.9in',
'margin-left': '0.9in',
'encoding': "UTF-8",
'header-center': 'YOUR HEADER',
'custom-header' : [
    ('Accept-Encoding', 'gzip')
],
'no-outline':None
}

you can add the header, which you need in the value for header-center

Share:
13,697
user3368835
Author by

user3368835

Updated on June 29, 2022

Comments

  • user3368835
    user3368835 almost 2 years

    I've been searching the web for examples of people using the pdfkit (python wrapper) in implementing headers and footers and could not find any examples.
    Would anyone be able to show some examples of how to implement the options in wkhtmltopdf using the pdfkit python wrapper?

  • florian
    florian about 4 years
    somehow my header file is ignored :(
  • AgentNirmites
    AgentNirmites over 2 years
    Yes, header file is ignored, any solution?
  • umair mehmood
    umair mehmood over 2 years
    it did not worked header and footer get ignored
  • Alba Hoo
    Alba Hoo over 2 years
    You need to do header_html.flush() after header_html.write(...), otherwise you are simply using a blank temp file for header and footer, so they looks like they are ignored.
  • AgentNirmites
    AgentNirmites over 2 years
    Where? @AlbaHoo ?
  • Alba Hoo
    Alba Hoo over 2 years
    @AgentNirmites after header_html.write(render_to_string(header_template, context).encode('utf-8')), you can try header_html.flush() to make this header_html file persistent with its content, I have also posted a proper answer with some working example in my case.