Django - 无法下载文件(改为显示为文本)

Django - can't download file (showed as text instead)

我的静态文件中有一个 pdf,我需要给它添加一些文本并让用户下载它,但是下载部分给我带来了一些问题,这是我的部分代码:

views.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(packet) 作为示例而不是让我下载我在浏览器上看到的文件:

%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,0U\H3T\pNYT^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 可下载?谢谢

如果文件响应是浏览器可识别的格式,则浏览器会显示文件响应。正如浏览器所识别的那样,浏览器会显示预览。如果想强制用户下载,有两种方法。

首先,如果您要 link 下载 url,请将下载属性添加到来自 html 的 link。 <a href="download/example.pdf" download>download me pls</a>

如果您想从 python 开始,或者 必须 在 python 中完成,那么您可以 return 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

资源:Having Django serve downloadable files

您可以用更少的代码来完成。如果你的文件路径是静态的而不是动态的,你可以用 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