4

I created a website which generates PDF using PDFKIT and I know how to install and setup environment variable path on Window. I managed to deploy my first website on Heroku but now I'm getting error "No wkhtmltopdf executable found: "b''" When trying to generate the PDF. I have no idea, How to install and setup WKHTMLTOPDF on Heroku because this is first time I'm dealing with Linux. I really tried everything before asking this but even following this not working for me. Python 3 flask install wkhtmltopdf on heroku

If possible, please guide me with step by step on how to install and setup this.

I followed all the resource and everything but couldn't make it work. Every time I get the same error. I'm using Django version 2. Python version 3.7.

This is what I get if I do heroku stack

Available Stacks cedar-14 container heroku-16 * heroku-18

Error, I'm getting when generating the PDF. No wkhtmltopdf executable found: "b''" If this file exists please check that this process can read it. Otherwise please install wkhtmltopdf - https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf

My website works very well on localhost without any problem and as far as I know, I'm sure that I have done something wrong in installing wkhtmltopdf.

Thank you

2 Answers2

3

It's non-trivial. If you want to avoid all of the below's headache, you can just use my service, api2pdf: https://github.com/api2pdf/api2pdf.python. Otherwise, if you want to try and work through it, see below.

1) Add this to your requirements.txt to install a special wkhtmltopdf pack for heroku as well as pdfkit.

git+git://github.com/johnfraney/wkhtmltopdf-pack.git
pdfkit==0.6.1

2) I created a pdf_manager.py in my flask app. In pdf_manager.py I have a method:

def _get_pdfkit_config():
     """wkhtmltopdf lives and functions differently depending on Windows or Linux. We
      need to support both since we develop on windows but deploy on Heroku.

     Returns:
         A pdfkit configuration
     """
     if platform.system() == 'Windows':
         return pdfkit.configuration(wkhtmltopdf=os.environ.get('WKHTMLTOPDF_BINARY', 'C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe'))
     else:
         WKHTMLTOPDF_CMD = subprocess.Popen(['which', os.environ.get('WKHTMLTOPDF_BINARY', 'wkhtmltopdf')], stdout=subprocess.PIPE).communicate()[0].strip()
         return pdfkit.configuration(wkhtmltopdf=WKHTMLTOPDF_CMD)

The reason I have the platform statement in there is that I develop on a windows machine and I have the local wkhtmltopdf binary on my PC. But when I deploy to Heroku, it runs in their linux containers so I need to detect first which platform we're on before running the binary.

3) Then I created two more methods - one to convert a url to pdf and another to convert raw html to pdf.

def make_pdf_from_url(url, options=None):
    """Produces a pdf from a website's url.
    Args:
        url (str): A valid url
        options (dict, optional): for specifying pdf parameters like landscape
            mode and margins
    Returns:
        pdf of the website
    """
    return pdfkit.from_url(url, False, configuration=_get_pdfkit_config(), options=options)

def make_pdf_from_raw_html(html, options=None):
    """Produces a pdf from raw html.
    Args:
        html (str): Valid html
        options (dict, optional): for specifying pdf parameters like landscape
            mode and margins
    Returns:
        pdf of the supplied html
    """
    return pdfkit.from_string(html, False, configuration=_get_pdfkit_config(), options=options)

I use these methods to convert to PDF.

apexdodge
  • 6,657
  • 4
  • 26
  • 33
3

Just follow these steps to Deploy Django app(pdfkit) on Heroku:

Step 1:: Add following packages in requirements.txt file

wkhtmltopdf-pack==0.12.3.0 
pdfkit==0.6.0

Step 2: Add below lines in the views.py to add path of binary file

import os, sys, subprocess, platform

if platform.system() == "Windows":
        pdfkit_config = pdfkit.configuration(wkhtmltopdf=os.environ.get('WKHTMLTOPDF_BINARY', 'C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe'))
else:
        os.environ['PATH'] += os.pathsep + os.path.dirname(sys.executable) 
        WKHTMLTOPDF_CMD = subprocess.Popen(['which', os.environ.get('WKHTMLTOPDF_BINARY', 'wkhtmltopdf')], 
            stdout=subprocess.PIPE).communicate()[0].strip()
        pdfkit_config = pdfkit.configuration(wkhtmltopdf=WKHTMLTOPDF_CMD)

Step 3: And then pass pdfkit_config as argument as below

pdf = pdfkit.from_string(html,False,options, configuration=pdfkit_config)
ZF007
  • 3,708
  • 8
  • 29
  • 48