41

是否可以在Django 视图中显示 PDF 文件,而不是让用户必须下载它才能看到它?

如果可能的话,它会怎么做?

这是我到目前为止所拥有的 -

@login_required
def resume(request, applicant_id):

    #Get the applicant's resume
    resume = File.objects.get(applicant=applicant_id)
    fsock = open(resume.location, 'r')
    response = HttpResponse(fsock, mimetype='application/pdf')

    return response
4

11 回答 11

47

Django 有一个专门用于返回文件的类FileResponse。它流式传输文件,因此您不必在返回之前将整个文件读入内存。干得好:

from django.http import FileResponse, Http404

def pdf_view(request):
    try:
        return FileResponse(open('foobar.pdf', 'rb'), content_type='application/pdf')
    except FileNotFoundError:
        raise Http404()

如果你有非常大的文件,或者如果你经常这样做,更好的选择可能是使用正常的服务器配置在 Django 之外提供这些文件。

于 2016-06-20T14:08:30.897 回答
37

简单地说,如果你有一个 PDF 文件并且你想通过 Django 视图输出它,你需要做的就是将文件内容转储到响应中并使用适当的 mimetype 发送它。

def pdf_view(request):
    with open('/path/to/my/file.pdf', 'r') as pdf:
        response = HttpResponse(pdf.read(), mimetype='application/pdf')
        response['Content-Disposition'] = 'inline;filename=some_file.pdf'
        return response
    pdf.closed

您可能可以直接返回响应而不指定 Content-Disposition,但这更好地表明了您的意图,并且还允许您指定文件名以防用户决定保存它。

另外,请注意,上面的视图不处理由于任何原因无法打开或读取文件的情况。由于它是用 完成的with,它不会引发任何异常,但您仍然必须返回某种响应。不过,你可以简单地提出一个Http404或什么。

于 2012-08-02T14:49:04.953 回答
14

PDF 文件必须以rb非打开方式打开r

def pdf_view(request):
    with open('/path / to /name.pdf', 'rb') as pdf:
        response = HttpResponse(pdf.read(),content_type='application/pdf')
        response['Content-Disposition'] = 'filename=some_file.pdf'
        return response
于 2015-04-18T14:00:10.667 回答
7

取出内联;如果您希望从服务器读取文件。而且,HttpResponsekwargmimetype已被替换为content_type

(response['Content-Disposition'] = 'inline;filename=some_file.pdf')

def pdf_view(request):
    with open('/app/../Test.pdf', 'r') as pdf:
        response = HttpResponse(pdf.read(),content_type='application/pdf')
        response['Content-Disposition'] = 'filename=some_file.pdf'
        return response
    pdf.closed
于 2014-11-04T10:06:35.763 回答
6

按照上面@radtek 的回答,我决定研究基于类的视图显示。我尝试使用View但它没有get_context_data()方法。

在这里寻找一些指导。我安顿下来,BaseDetailView因为我只想显示一个对象。

from django.http import FileResponse
from django.shortcuts import get_object_or_404
from django.views.generic.detail import BaseDetailView

class DisplayPdfView(BaseDetailView):
    def get(self, request, *args, **kwargs):
        objkey = self.kwargs.get('pk', None) #1
        pdf = get_object_or_404(Pdf, pk=objkey) #2
        fname = pdf.filename() #3
        path = os.path.join(settings.MEDIA_ROOT, 'docs\\' + fname)#4
        response = FileResponse(open(path, 'rb'), content_type="application/pdf")
        response["Content-Disposition"] = "filename={}".format(fname)
        return response

评论

pk1 此行访问由调用视图的 url 传递的命名参数。

2 此行获取实际的 pdf 模型对象。

3 我filename(self): return os.path.basename(self.file.name)在模型中定义了一个方法来帮助我只获取文件名和扩展名。

4 此行获取完整的文件路径。

然后按照上述答案中的说明使用文件响应。还记得使用rb阅读pdf文件

于 2017-09-17T19:14:52.223 回答
4

Here is a typical use-case for displaying a PDF using class-based views:

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse

class DisplayPDFView(View):

    def get_context_data(self, **kwargs):  # Exec 1st
        context = {}
        # context logic here
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data()
        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'inline; filename="worksheet_pdf.pdf"'  # Can use attachment or inline

        # pdf generation logic here
        # open an existing pdf or generate one using i.e. reportlab

        return response

# Remove login_required if view open to public
display_pdf_view = login_required(DisplayPDFView.as_view())

For generating your own pdf with reportlab see the Django project Docs on PDF Generation.

Chris Pratt's response shows a good example of opening existing PDFs.

于 2015-01-22T15:00:42.327 回答
0

浏览器不是 PDF 阅读器(除非它们有适当的插件/插件)。

您可能希望将 PDF 呈现为 HTML,这可以从 backendfrontend完成。

于 2012-08-02T14:52:30.953 回答
0

我只是把它扔在那里。

您可以简单地将 PDF 简历添加到静态文件中。

如果您使用白噪声来提供静态文件,那么您甚至不需要制作视图。然后在静态位置访问您的简历。

我添加了我的,这里是:TIm-D_Nice.pdf

警告:这并不能解决问题中的login_required要求

于 2017-12-10T07:27:42.237 回答
0

它对我有用

import re, os
import os
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def export_auto_doc(request):
    name = request.GET.get('name', "")
    filename = "path/to/file"+name+".pdf"
    try:
        if not re.search("^[a-zA-Z0-9]+$",name):
            raise ValueError("Filename wrong format")
        elif not os.path.isfile(filename):
            raise ValueError("Filename doesn't exist")
        else:
            with open(filename, 'r') as pdf:
                response = HttpResponse(pdf.read(), content_type='application/pdf')
                response['Content-Disposition'] = 'inline;filename='+name+'.pdf'
                return response
            pdf.closed
    except ValueError as e:
        HttpResponse(e.message)
于 2016-10-21T15:51:01.363 回答
0

使用 pdf 标签的 iframe url=url 并提供该 pdf 的 url 并确保您的用户将完全控制项目然后 pdf 将显示在网页屏幕上

于 2021-10-22T17:31:29.807 回答
0

最简单的方法可能是在模板中使用锚点。例如,如果您正在使用 Django 的模板引擎(大多数搜索此引擎的人可能都是),只需通过锚点将其作为静态文件提供。

在包含文件链接的模板中,在最顶部添加

{% load static %}

然后,无论你想链接到你的 pdf,把

<a href="{% static 'relative/path/file.pdf' %}">Click me</a>

第一行告诉 Django 在settings.py. 您在锚标记中使用的路径相对于您在 中配置为静态目录的任何目录settings.py。当您单击呈现的链接时,它应该在您的浏览器中显示 PDF,前提是您的静态文件路径正确。

于 2018-03-26T19:38:33.593 回答