Loading images from an AWS bucket media folder to a HTML pdf template

Viewed 121

I am trying to generate a PDF file out of a post created by a user, and include an image, which I want to store in an AWS bucket.

This is how it was working with my own file system

My function to generate a pdf in views.py:

def form_render_pdf_view(request, *args, **kwargs):
    pk = kwargs.get('pk')
    form = get_object_or_404(Post, pk=pk)

    template_path = 'form/pdf2.html'
    context = {
    'form': form
}
# Create a Django response object, and specify content_type as pdf
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'filename="report.pdf"'
# find the template and render it.
    template = get_template(template_path)
    html = template.render(context)

# create a pdf
    pisa_status = pisa.CreatePDF(
    html, dest=response)

    if pisa_status.err:
       return HttpResponse('We had some errors <pre>' + html + '</pre>')
    return response

And rendering the image in the html template

    <div>
        <img src="{{form.image.path}}">
    </div>

Now after uploading the files in a bucket it doesn't seem to work. The image is being stored there after uploading the post, but when creating the PDF the image is not displayed.(And it gives me an error: This backend doesn't support absolute paths). I tried to change the image source in the HTML template but it still didn't work.

1 Answers

Here is how I was able to implement it successfully. Hope it helps

url.py

path('foo/bar/<str:bar_id>/report/pdf/', getPdf,name="bar-report-pdf"),

process.py

from io import BytesIO
from django.conf import settings
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa

def html_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html  = template.render(context_dict)

    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), 
                            result,
                            )
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None

do not use the link_callback attribute of the pisaDocument when using external url

view.py

from foo.process import html_to_pdf 

def getPdf(request,bar_id):

    image_set = Bar.objects.filter(id=bar_id).all()
    
    context = {
        'title':"Inspection Report",
        "images": image_set,
        }

    open('templates/temp.html', "w").write(render_to_string('app/bar-report-pdf.html',context ))

    pdf = html_to_pdf('temp.html')
         
    return HttpResponse(pdf, content_type='application/pdf')

bar-report-pdf.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {% for image in images %}
            <img class="d-block img-fluid" src="{{image.thumbnail_url_public}}" alt="{{forloop.counter}}">
    {% endfor %}
</body>
</html>

here image.thumbnail_url_public is a text field containing public s3 image url. you can also use the presigned url if its a private s3 bucket.

hope it helps

Related