3

I am trying to generate and output PDF from a django view. I followed the example in django documentation using ReportLab but the downloaded PDF is not opening in any PDF readers.

I use Python 3.7.0, Django==2.1.3, reportlab==3.5.12. I tried adding content_type="application/pdf" to 'FileResponse` but still having the same issue.

import io
from django.http import FileResponse
from reportlab.pdfgen import canvas

def printPDF(request):
    # Create a file-like buffer to receive PDF data.
    buffer = io.BytesIO()

    # Create the PDF object, using the buffer as its "file."
    p = canvas.Canvas(buffer)


    p.drawString(100, 100, "Hello world.")


    p.showPage()
    p.save()

    return FileResponse(buffer, as_attachment=True, filename='hello.pdf')

The generated PDF should be opening in all PDF readers. But I am getting 'Failed to load PDF document.'

Nigel
  • 376
  • 4
  • 13

2 Answers2

5

buffer = BytesIO() is used instead of a file to store the pdf document. Before returning it with FileResponse you need to reset the stream position to its start:

buffer.seek(io.SEEK_SET)

Now the pdf download should work as expected.

cuto
  • 121
  • 4
3

There seems to be something fishy going on with the interaction of BytesIO and FileResponse. The following worked for me.

def printPDF(request):
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=hello.pdf'
    p = canvas.Canvas(response)
    p.drawString(100, 100, "Hello world.")
    p.showPage()
    p.save()
    return response
  • Seems to be a bug. I ended up using `xhtml2pdf`. – Nigel Jan 15 '19 at 05:40
  • I just came across https://github.com/unbit/uwsgi/issues/1126, which has been an outstanding uwsgi/Python 3/`BytesIO` bug for almost 4 years. – Geoff Sep 20 '19 at 23:45