2012-08-02 150 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

警告:這並不解決問題