0

I have seen many answers to questions like this, but none has solved my problem...

I want to produce a pdf in the backend and then download it to the user. So I have a basic blank page with a button. For that button there is a jQuery function:

  $.post("{% url 'printReport' %}", 
  {
    'params' : JSON.stringify({
      'reportcode' : 'HelloWorld',
    })
  }, function(data, status) {
    $("#testZone").text(data)
  });

On the server side, I produce the pdf and save it locally in the server folder. This goes perfect. Then, in the views file I have this:

def printRreport(request):
  if request.method=="POST":
    res = producePdf(request) #works fine! the PDF is birght an shiny, saved on the server
    response = HttpResponse(res.data,content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="report.pdf"' #setting response headers
    return response

where res.data is actually open(pdf_path,'r').read()

this is 70% fine, because the browser actually receives the pdf data inside the request response (I can see it on the dev console). It's 30% wrong because this does not give me a download dialog and does not allow me to save a pdf file on the client side.

What is wrong here? In my case I opted by using a POST method, I know it's debatable, but I don't think that is the problem...

Edit: I found a solution for this, maybe not optimal, but it works. I marked below the answer I ended up following. I kept the code above, but I decided to generate the pdf file on the first view (which receives the POST request), then redirect the user to another view where it would download it. And it works!

I'll still check this as suggested by Abdul though.

Thanks!

K09P
  • 480
  • 4
  • 13

1 Answers1

1

Instead of using HttpResponse try using FileResponse:

from django.http import FileResponse

def printRreport(request):
    res = producePdf(request)
    file_ptr = # something that would get you something like open(pdf_path,'rb')
    return FileResponse(file_ptr)

Now in your javascript the problem is you are making the request as ajax and the content is with javascript, an easier thing would be to let your browser handle the url (It is a file download anyway no need for ajax):

var link = document.createElement("a");
link.download = "Report";
link.href = "{% url 'printReport' %}";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

Note: If you don't need to run this dynamically consider just an anchor with the url. Instead of javascript.

Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
  • Thanks, it's a very good help! I'll use this information to solve it, though it is not the solution to the problem. I used an Ajax request because I need to send extra information on the request body. If I just do a traditional link, I don't have that option... – K09P Feb 06 '21 at 16:53
  • 1
    @K09P this [answer by John Culviner](https://stackoverflow.com/a/9970672/14991864) might be helpful for the download by ajax. – Abdul Aziz Barkat Feb 06 '21 at 17:19