Here is a very quick guide to generated a PDF from HTML and download it using Flask.
First of all add these two dependencies in you requirements.txt file and install them using pip
pdfkit==1.0.0
wkhtmltopdf==0.2
Then install the pdf engine running:
sudo apt install wkhtmltopdf
In your code, import pdfkit and render an HTML template. Then put the output into pdfkit and return the PDF as following:
import pdfkit @app.route("/download") def route_download(): # Get the HTML output out = render_template("export.html") # PDF options options = { "orientation": "landscape", "page-size": "A4", "margin-top": "1.0cm", "margin-right": "1.0cm", "margin-bottom": "1.0cm", "margin-left": "1.0cm", "encoding": "UTF-8", } # Build PDF from HTML pdf = pdfkit.from_string(out, options=options) # Download the PDF return Response(pdf, mimetype="application/pdf")
You can assign a download filename adding the following header to the Response
headers = {"Content-Disposition": "attachment;filename=myname.pdf"}
return Response(pdf, mimetype="application/pdf", headers=headers)
Troubleshooting
- Cannot find wkhtmltopdf executable
OSError: No wkhtmltopdf executable found
In this case you have to install wkhtmltopdf:
$ sudo apt install wkhtmltopdf
- Protocol error
Exit with code 1 due to network error: ProtocolUnknownError
In this case you are not using the http or https protocols in some HTML references, for example in an image tag. To fix this error try to specify the entire URL starting from protocol.
<img src="/myimg.png"> # Wrong
<img src="https://myurl.me/static/images/myimg.png"> # Ok
If you want to render the full URL dynamically via Flask you can add edit your code as following:
from urllib.parse import urlparse
# <img src="{{root}}/static/images/myimg.png">
parsed_url = urlparse(request.url)
root= parsed_url.scheme + "://" + parsed_url.netloc
out = render_template("export.html", root=root)
References
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.