通过对用户进行身份验证,使用 Django REST 框架下载文件

Posted

技术标签:

【中文标题】通过对用户进行身份验证,使用 Django REST 框架下载文件【英文标题】:Download a file using Django rest framework by authenticating the user 【发布时间】:2018-08-18 20:53:51 【问题描述】:

我正在做一个项目,我使用 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(vuejs 的 s-s-r)。这是一段小sn-p代码,用户可以通过点击目标空白链接下载文件。:

<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 是匿名的。

有没有其他方法可以通过检查请求的用户是否是票证的所有者来下载文件?

【问题讨论】:

删除target="_blank" 有帮助吗?我认为令牌没有被传递,因为链接正在新选项卡中打开,但不确定。 您使用的是哪种身份验证 Session 或 Token? @ChintanJoshi 不。删除 target="_blank" 没有帮助。 @IgorYalovoy 我正在使用令牌身份验证 (jwt)。 【参考方案1】:

因为您使用的是 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 不应更改。你做的就是要走的路。

您的链接现在需要调用新的前端函数,而不仅仅是&lt;a href

编辑

几年前我问过这样的question。您可能会在那里找到一些帮助。

浏览器兼容性

blob、createElement、createObjectURL

【讨论】:

你能告诉我浏览器与这种方法的兼容性吗? 在 Chrome 中为我工作。 Firefox 通常不喜欢这样的东西,除非它是由用户触发的。我怀疑@Aamu 你应该没事

以上是关于通过对用户进行身份验证,使用 Django REST 框架下载文件的主要内容,如果未能解决你的问题,请参考以下文章

JWT 身份验证:使用 UI 令牌对 Graphene/Django (GraphQL) 查询进行身份验证?

django rest framework jwt 使用电子邮件和密码进行身份验证

android to django - 如何对用户进行身份验证

维护用户会话而无需将用户保存在 django 身份验证系统中

检测用户首次使用 Django Rest Framework 进行身份验证

使用多个数据库进行 Django 身份验证