2012-08-02 156 views
15

是否可以在中显示PDF文件Django视图,而不是让用户不得不下载它才能看到它?如何在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 

回答

23

简单地说,如果你有一个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 

您可能只需直接返回响应而无需指定内容处置,但更好的显示你的意图,并允许您指定以防万一用户决定保存的文件名。

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

+0

,直到我改变了'它不为我工作的MIME类型=的login_required要求'application/pdf' to'contenttype ='application/pdf'' – 2015-12-10 23:26:13

+2

content_type,也pdf.closed在那里没有效果 – amchugh89 2016-02-22 13:47:28

+0

可以在关闭文件之前返回吗?我想不是。 – azuax 2016-04-19 20:03:14

1

浏览器不是PDF阅读器(除非他们有正确的插件/插件)。

您可能希望将PDF呈现为HTML,而不是使用from the backendthe frontend

5

取出内联;如果你想让你的文件从服务器上读取。而且,在HttpResponse kwarg mimetype已取代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 
1

下面是一个典型的用例使用基于类的视图中显示PDF:

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()) 

对于生成自己的PDF reportlab请参阅Django project Docs on PDF Generation

Chris Pratt的回复显示了打开现有PDF的一个很好的例子。

6

如果您在Windows计算机上工作,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 
+0

使用'r'打开并显示pdf。 – yndolok 2015-11-18 17:29:25

10

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服务器常规配置之外的这些文件。

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) 
0

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

我看了here的一些指导。我解决了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 

评论

1此行访问由URL调用视图通过命名参数pk

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

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

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

然后使用上面答案中所述的文件响应。还记得用rb来阅读pdf文件

-1

我只是把它扔在那里。

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

如果您使用白噪声服务您的静态文件,那么您甚至不需要制作视图。只需在静态位置访问您的简历即可。

我说我的,那就是:https://www.jefferythewind.com/static/main/resume/TIm-D_Nice.pdf

警告:这并不解决问题