I'm having a problem getting my pdf file to display on the browser using X-Accel-Redirect
. Linking the file URL directly from Nginx public location works out fine. However, restricting access to the location by adding in "internal" and calling X-Accel-Redirect
from Django's HttpResponse()
sends the pdf file as plaintext, as it would any other static file (css, js, html).
Python Response
response = HttpResponse()
response['Content-Type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment; filename=example.pdf'
response['X-Accel-Redirect'] = '/media/file-pdf/example.pdf'
return response
Nginx Location
location /media/{
internal;
alias /var/www/media/;
default_type application/pdf;
}
Javascript
$.ajax({
url: http://www.example.com/pdf-api/,
type: 'GET',
success: function(data) {
window.open(data);
console.log(data);
},
});
Sample pdf as text received (as seen on browser console)
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20180925202407-08'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20180925202407-08'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 856
>>
My question is: What is the correct way to serve restricted pdf (or any file) to users using Python + Django + Nginx? Or should I convert the binary data sent into pdf on the browser's end?
I think what you're doing is correct. Browsers can't just "display" the PDF file per se. I believe what you might be referring to is Chrome's automatic display of PDF files when you open them? Actually those are triggered by downloads on the frontend.
After your AJAX call receives the PDF from the backend, you have a few options from here:
Embed a PDF viewer in your UI and pass the URL of the PDF to the viewer (such as ViewerJS or pdf.js).
Create a Blob with the data and attach it as an href to a hidden anchor tag and use javascript to force
click()
action on it to trigger the download. You might find some inspiration here