Django-React Link to Download PDF

farhanghazi97
3 min readAug 24, 2020

--

This is a feature I’ve had to implement very recently for a project and it took some tinkering to finally get it working. I hope this helps anyone whose having to deal with such a use case!

Step 1

Get Django to locate the files you want to serve.

Django by default stores files locally using the MEDIA_ROOT and MEDIA_URL settings (defined within settings.py). Hence, we’ll need to define a folder that will house the files we want to make available for download via our application. Create a new folder named media and place it in the root directory of your Django application. You can then populate this folder with any and all files that you wish to serve via your application.

Next, let’s go ahead and update our settings.py so that Django can start looking for the correct files in the correct place. Add the following line at the end of your settings.py file:

MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)

Step 2

Set up Django view to download desired file.

We’ll now write backend code to set up a view that will allow users of our application to download files (visually, this will be equivalent to a user clicking some button that says ‘Download’ and the file magically downloading). To keep things simple, we’ll write up a simple function-based API view (note: the following endpoint is set up using DRF (Django Rest Framework)). Within views.py in your application folder, go ahead and write up the following view function:

from django.core.files import File
from django.http import HttpResponse
from rest_framework.decorators import api_view
from app.settings import BASE_DIR, MEDIA_ROOT
@api_view(['GET'])
def DownloadPDF(self):
path_to_file = MEDIA_ROOT + '/filename.pdf'
f = open(path_to_file, 'rb')
pdfFile = File(f)
response = HttpResponse(pdfFile.read())
response['Content-Disposition'] = 'attachment;
return response

Simply replace the filename with the appropriate name of the PDF file that you want to make available for download.

Step 3

Set up URL to trigger view that initiates the file download

We now create a corresponding URL to the trigger the view. Let’s look at the code.

from django.urls import path
from api.views import DownloadPDF
urlpatterns = [
path('download/', DownloadPDF, name='download_pdf'),
]

That’s it for backend. Let’s now switch over to React and connect our frontend. We now simply need to query our API service and let the backend do the rest. However. there is a common pitfall that we’ll address.

Step 4

Query API endpoint to download file

The frontend code is fairly simple. To make our life easier, we’ll make use of this handy npm package called js-file-download that takes care of the technicalities involved in actually downloading the file. Let’s go ahead and install the package.

npm install js-file-download --save

Now, we write up our handler and corresponding UI code.

import axios from 'axios';var fileDownload = require('js-file-download');function App() {
const handlePDFDownload = () => {
axios.get('api/endpoint/to/view/', {
responseType: 'blob',
}).then(res => {
fileDownload(res.data, 'filename.pdf');
console.log(res);
}).catch(err => {
console.log(err);
})
}
return (
<div>
<button
onClick={() => handlePDFDownload()}>Download File!
</button>
</div>
)
}

Some things to note:

In the above GET request, you’ll want to make note of the responseType parameter that has been specified as blob. Upon further inspection, I’ve learned that when we download files, they are actually returned in response as blob objects which simply represent file-like objects of immutable, raw data. In order for them to be retrieved as downloadable files, we’ll want to explicitly specify this in our request.

If you’ve gotten so far without any disruption, you should (hopefully) have a button set up that allows you to download a PDF of your choice. I hope this was helpful!

Feel free to let me know if this helped you. Thanks for reading!

--

--

farhanghazi97

Just writing about stuff I got stuck with, so that you guys don’t have to struggle with the same things. Find out more: https://www.farhanghazi.xyz/