Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download a file using Django rest framework by authenticating the user

I am working on a project where I am using Django as the back end. I am working with Django rest framework, and I have an API to download a File.

@detail_route(methods=['GET'], permission_classes=[IsAuthenticated])
def test(self, request, pk=None):
    try:
        ticket = Ticket.objects.get(id=pk, user=request.user)
        file_path = ticket.qrcode_file.path
        if os.path.exists(file_path):
            with open(file_path, 'rb') as fh:
                response = HttpResponse(fh.read(), content_type="image/jpeg")
                name = "%s %s %s %s.jpg" % (ticket.show.title, datetime.strftime(ticket.show.date_time,
                                                                                       "%H_%M_%p"),
                                            datetime.strftime(ticket.show.date_time, "%d %B %Y"), ticket.id)
                response['Content-Disposition'] = "attachment; filename=%s" % name.replace(" ", "_")
                return response
        return Response({'error': 'Ticket doest not belong to requested user.'}, status=status.HTTP_403_FORBIDDEN)
    except Ticket.DoesNotExist as e:
        return Response({'error': str(e)}, status=status.HTTP_404_NOT_FOUND)

On the front-end I am using Nuxtjs (ssr for vuejs). This is a little snippet of code, where a user can download the file by clicking a link of target blank.:

<a class="downloadBtn" target="_blank" :href="`${baseURL}/payments/api/tickets/${ticket.id}/download_ticket/`">Download e-ticket</a>

The web app is running on Nuxtjs server (localhost:3000) and Django server is running on localhost:8000, only the API is used to communicate between the Nuxtjs and Django by using the auth token.

When I click the download link it opens up a new tab and make a request from that new tab, where no token is passed with the request. And since, the django view to download the ticket is permission_classes=[IsAuthenticated] I cannot be authenticated as request.user is anonymous.

Is there any other way that I can make it work to download the file by checking whether the requested user is the Ticket's owner?

like image 232
Aamu Avatar asked Mar 10 '18 10:03

Aamu


1 Answers

Because you are using JWT, you should download the file from your frontend after requesting it from your api using some sort of ajax request and the JWT header.

some_api_request_hendler().then(function (response) {
    var file = new Blob([response.data], {type: response.headers("Content-Type")});
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(pdf);
    link.download = "the_new_file_name";
    link.click();
});

I'm using this answer as an example. Your API should not be changed. The way you did it is the way to go.

And your link now need to call your new frontend function instead of just <a href.

Edit:

I asked a question like that a few years ago. You might find some help there.

Browser Compatibility

blob, createElement, createObjectURL

like image 54
Gal Silberman Avatar answered Sep 30 '22 04:09

Gal Silberman