我的静态文件中有一个pdf,我需要添加一些文本并让用户下载,但下载部分给我带来了一些问题,这是我的部分代码:
视图.py
import io
from werkzeug.wsgi import FileWrapper
from pathlib import Path
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from django.http import HttpResponse, FileResponse
def downloadpdf(request):
pdf_path = (Path.home()/"bot"/"mysite"/"static"/"images"/"tesseragenerica.pdf")
# 1
pdf_reader = PdfFileReader(str(pdf_path))
packet = io.BytesIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
testo = "text to add" #in future "text to add" will be the username
can.drawString(5, 5, testo)
can.save()
#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PdfFileReader(packet)
# read your existing PDF
existing_pdf = PdfFileReader(open("/home/myusername/bot/mysite/static/images/tesseragenerica.pdf", "rb"))
output = PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
page = existing_pdf.getPage(0)
page.mergePage(new_pdf.getPage(0))
output.addPage(page)
# finally, write "output" to a real file
outputStream = open("destination3.pdf", "wb")
output.write(outputStream)
outputStream.close()
return FileResponse(FileWrapper(packet), as_attachment=True, filename='hello.pdf')
将文本添加到pdf的代码是正确的,因为在本地它是有效的,所以我认为问题是我把什么作为FileResponse的第一个参数,例如,如果我放FileWrapper(数据包(而不是让我下载文件,我会在浏览器上看到:
%PDF-1.3 %���� ReportLab Generated PDF document http://www.reportlab.com 1 0 obj << /F1 2 0 R >> endobj 2 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> endobj 3 0 obj << /Contents 7 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 4 0 obj << /PageMode /UseNone /Pages 6 0 R /Type /Catalog >> endobj 5 0 obj << /Author (anonymous) /CreationDate (D:20210718122806+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20210718122806+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (unspecified) /Title (untitled) /Trapped /False >> endobj 6 0 obj << /Count 1 /Kids [ 3 0 R ] /Type /Pages >> endobj 7 0 obj << /Filter [ /ASCII85Decode /FlateDecode ] /Length 97 >> stream GapQh0E=F,0UH3TpNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISh__N8"+NKVeK&quKrKuB2i9neZ[Kb,ht63StAffBaV~>endstream endobj xref 0 8 0000000000 65535 f 0000000073 00000 n 0000000104 00000 n 0000000211 00000 n 0000000404 00000 n 0000000472 00000 n 0000000768 00000 n 0000000827 00000 n trailer << /ID [<75dce57879667ca53ee6edf7352f4f98><75dce57879667ca53ee6edf7352f4f98>] % ReportLab generated PDF document -- digest (http://www.reportlab.com) /Info 5 0 R /Root 4 0 R /Size 8 >> startxref 1013 %%EOF
我认为这是一个pdf文件,但不明白为什么浏览器会显示它而不是下载它。我认为(并希望(我已经接近解决方案,但我不知道我做错了什么。我该怎么做才能下载pdf?感谢
如果文件响应是浏览器可识别的格式,则浏览器会显示该文件响应。当浏览器识别它时,浏览器会显示预览。如果您想强制用户下载它,有两种方法。
首先,如果要链接到下载url,请从html向链接添加一个下载属性。<a href="download/example.pdf" download>download me pls</a>
如果您想在python中执行,或者让在python中进行,那么您可以返回一个HttpResponse
对象,但其content_type会强制下载。示例:
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/force-download")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
资源:让Django提供可下载文件
您可以用更少的代码来完成。如果您的文件路径是静态的,而不是像下面这样的动态路径,您可以使用file_path = "/static/your_file_path/"
进行更改
def download_file_from_server(request):
file_path = request.GET["file_path"]
file = open(os.path.join(settings.BASE_DIR, file_path), 'rb')
response = FileResponse(file)
return response
当您返回FileResponse(或HttpResponse(时,请确保您将其返回到视图调用方,并且没有更改。在撕了我的头发几天后,读了这个问题和几个相关的问题,听到每个人都说"只需使用as_attachment=True的FileResponse,您的文件就会下载&";,看到我的文件显示为网页,我一点也不高兴。
我最终决定跟踪我的代码执行,从跟踪
resp = FileResponse(open(fName+ExcelWorkbook_fileext, 'rb'),
as_attachment=True,
filename=SQLResultPrefix+ExcelWorkbook_fileext)
# lines below are needed if you use HttpResponse rather than FileResponse(..., as_attachment=True, ...)
# resp['Content-Disposition'] = 'attachment; filename="' + SQLResultPrefix+ExcelWorkbook_fileext + '"'
# resp['Content-Type'] = 'application/vnd.ms-excel'
return resp
返回的不是原始视图调用程序,而是";交通警察;负责解析和调度用户请求的例程。被调用的例程将把它的HTML放在一起,并通常向交通警察返回一个render(req、templt、cntext(。上面的代码将其响应返回给交通警察。
然后流量警察设置retHTTP=返回值,然后设置
return HttpResponse(retHTTP)
如果你只是显示网页,这不是问题,但如果retHTTP包含HTML标头信息(如Content-Disposition(,HttpResponse会去掉它,并用自己的标头替换它,适合显示页面。
这个故事的寓意是:当您返回FileResponse(或HttpResponse(时,请确保您正在返回它(未更改(以查看调用者
如果不清楚的话,最终让我下载文件的修复方法是将交警中的上述行更改为
if isinstance(retHTTP, HttpResponseBase):
return retHTTP
else:
return HttpResponse(retHTTP)
(这确实是它最初应该有的样子!(