简体   繁体   English

通过验证用户使用Django rest框架下载文件

[英]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. 我正在开发一个项目,我使用Django作为后端。 I am working with Django rest framework, and I have an API to download a File. 我正在使用Django休息框架,我有一个API来下载文件。

@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). 在前端我使用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. Web应用程序在Nuxtjs服务器(localhost:3000)上运行,Django服务器在localhost:8000上运行,只有API用于通过使用auth令牌在Nuxtjs和Django之间进行通信。

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. 因为,下载票证的django视图是permission_classes=[IsAuthenticated]我无法通过request.user匿名进行身份验证。

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? 有没有其他方法可以让我通过检查所请求的用户是否是Ticket的所有者来下载文件?

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. 因为您正在使用JWT,所以您应该在使用某种ajax request和JWT标头从api请求它后从您的前端下载该文件。

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. 您的API不应更改。 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 . 你的链接现在需要调用你的新前端函数,而不仅仅是<a href

Edit : 编辑

I asked a question like that a few years ago. 几年前我问过这样的问题 You might find some help there. 你可能会在那里找到一些帮助。

Browser Compatibility 浏览器兼容性

blob , createElement , createObjectURL blobcreateElementcreateObjectURL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM