I wrote a working application in python2.7 and Flask. One of the things it does is download a PDF invoice. It's working fine.
Now I am doing a new app that also allows downloading a PDF invoice, but I am using Python3 this time. I can save the file to the server and get a perfectly working PDF, but if I try to send it to the browser, the resulting file is corrupted.
Here is the download function:
@mod.route('/get_invoice/<invoice_id>')
def get_invoice(invoice_id):
invoice = Invoices.query.filter_by(id=invoice_id).all()
pdf_generator = PDFInvoice(invoice)
pdf = pdf_generator.new()
response = make_response(pdf.output(dest='S'))
response.headers['Content-Disposition'] = 'attachment; filename="invoice.pdf"'
response.headers['Content-Type'] = 'application/pdf'
return response
This is nearly identical to the working function in the older Python2.7 application.
To expand, it is turning this (working PDF):
x�3R��2�35W(�r
Q�w3T��30P^HISp^M^A�^X^[�^YZ*�^[^Z�^Y�*��(h�e^Vg�(�^V+$�(����e����奖h*�d��^@^@�v^T�
into this (corrupted PDF):
x^Ü3Rðâ2Ð35W(çr
QÐw3T°Ô30P^HISp^M^A^É^X^[è^YZ*^Ø^[^Zê^Y^Û*^Ĥ(h^Äe^Vg^Ö(^Ô^V+$^Ö(^Ô^×^×ëe§æ^Õèå¥^Öh*^Äd^Áô^@^@øv^TÂ
The rest of the pdf's data is text strings, and they appear to be unchanged. So it seems to be an encoding issue someplace.
FPDF outputs a str
which in Python 2 is basically equivalent to bytes
, but in Python 3 is unicode, not bytes. Straight from the docs:
If you are using Python 3.x you have to use
pdf.output(dest='S').encode('latin-1')
in order to get the output, if you don't do so the generated PDF will be invalid