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

时间:2018-03-10 10:38:23

标签: javascript python django vue.js nuxt.js

我正在开发一个项目,我使用Django作为后端。我正在使用Django rest框架,我有一个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)

在前端我正在使用Nuxtjs(ssr for vuejs)。这是一小段代码,用户可以通过单击目标空白链接来下载文件。

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

Web应用程序在Nuxtjs服务器(localhost:3000)上运行,Django服务器在localhost:8000上运行,只有API用于通过使用身份验证令牌在Nuxtjs和Django之间进行通信。

当我单击下载链接时,它会打开一个新选项卡,并从该新选项卡发出请求,其中没有令牌与请求一起传递。因为,下载票证的django视图是permission_classes=[IsAuthenticated]我无法通过身份验证,因为request.user是匿名的。

通过检查所请求的用户是否是Ticket的所有者,还有其他方法可以让我下载文件吗?

1 个答案:

答案 0 :(得分:7)

由于您使用的是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();
});

我以answer为例。您的API不应更改。你做到这一点的方式是要走的路。

现在您的链接需要调用新的前端功能,而不仅仅是<a href

修改

几年前,我问了question这样的问题。你可能会在那里找到一些帮助。

浏览器兼容性

blobcreateElementcreateObjectURL