Python Flask 将 PDF 作为自己的页面处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18281433/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:23:00  来源:igfitidea点击:

Flask handling a PDF as its own page

pythonpdfwebflask

提问by Stealthy Stan

For my personal website, I want to have a separate page just for my résumé, which is a PDF. I've tried multiple ways, but I can't figure out how to get flask to handle a PDF.

对于我的个人网站,我希望有一个单独的页面用于我的简历,它是一个 PDF。我尝试了多种方法,但我不知道如何让烧瓶处理 PDF。

回答by AlexLordThorsen

You have two options. You can either render a template that uses a static PDF file or render a template that generates a PDF. I'd personally go with the first option.

你有两个选择。您可以渲染使用静态 PDF 文件的模板或渲染生成 PDF 的模板。我个人会选择第一个选项。

This SO question is dedicated to how to write an HTML page that returns a PDF. You can use this in your jinja2 template.

这个 SO 问题致力于如何编写返回 PDF 的 HTML 页面。您可以在 jinja2 模板中使用它。

Here's a quick and dirty way to get it done.

这是完成它的一种快速而肮脏的方法。

<embed src="http://yoursite.com/the.pdf" width="500" height="375">

Or, you can create a jinja2 template which sets all the headers required to return a PDF and then say,

或者,您可以创建一个 jinja2 模板,该模板设置返回 PDF 所需的所有标题,然后说,

<img src="{{ url_for('static', filename='img.png', _external=True) }}" />

with a view function called static that returns the pdf.

使用名为 static 的视图函数返回 pdf。

You can read more about the second option at this flask snippet

您可以在此烧瓶代码段中阅读有关第二个选项的更多信息

回答by teechap

A note for anyone that came to this question because they're trying to serve PDF files from a database with Flask. Embedding a PDF when the file is stored on a database isn't as simple as when it's in the static folder. You have to use the make_responsefunction and give it the appropriate headers so the browser knows what to do with your binary PDF data, rather than just returning it from the view function like normal. Here's some pseudocode to help:

给任何遇到此问题的人的说明,因为他们试图使用 Flask 从数据库中提供 PDF 文件。当文件存储在数据库中时嵌入 PDF 不像在静态文件夹中那样简单。您必须使用该make_response函数并为其提供适当的标题,以便浏览器知道如何处理您的二进制 PDF 数据,而不是像往常一样从视图函数中返回它。这里有一些伪代码可以提供帮助:

from flask import make_response

@app.route('/docs/<id>')
def get_pdf(id=None):
    if id is not None:
        binary_pdf = get_binary_pdf_data_from_database(id=id)
        response = make_response(binary_pdf)
        response.headers['Content-Type'] = 'application/pdf'
        response.headers['Content-Disposition'] = \
            'inline; filename=%s.pdf' % 'yourfilename'
        return response

You can change the Content-Disposition from 'inline' to 'attachment' if you want the file to download rather than display in the browser. You could also put this view in a subdomain, e.g. docs.yourapp.com rather than yourapp.com/docs. The last step is to actually embed this document in the browser. On any page you'd like, just use rawrgulmuffin's strategy:

如果您希望文件下载而不是显示在浏览器中,您可以将 Content-Disposition 从“inline”更改为“attachment”。您也可以将此视图放在子域中,例如 docs.yourapp.com 而不是 yourapp.com/docs。最后一步是将这个文档实际嵌入到浏览器中。在您想要的任何页面上,只需使用 rawrgulmuffin 的策略:

<embed src="/docs/pdfid8676etc" width="500" height="375">

You could even make the src dynamic with a Jinja2 template. Let's put this in doc.html (note the curly brackets):

您甚至可以使用 Jinja2 模板使 src 动态化。让我们把它放在 doc.html 中(注意大括号):

<embed src="/docs/{{doc_id}}">

Then in a view function, you just return the rendered template with the appropriate doc_id:

然后在视图函数中,您只需返回具有适当 doc_id 的渲染模板:

from flask import render_template

@app.route('/<id>')
def show_pdf(id=None):
    if id is not None:
        return render_template('doc.html', doc_id=id)

This embeds a document the user requested from a database with a simple GET request. Hope this helps anyone working with lots of PDFs in a database!

这嵌入了用户通过简单的 GET 请求从数据库中请求的文档。希望这可以帮助任何在数据库中处理大量 PDF 的人!

回答by M.javid

You can use flask send_fileor send_static_filefunction in 5lines:

您可以在5行中使用烧瓶send_filesend_static_file函数:

from flask import send_file, current_app as app

@app.route('/show/static-pdf/')
def show_static_pdf():
    with open('/path/of/file.pdf', 'rb') as static_file:
        return send_file(static_file, attachment_filename='file.pdf')

This snippet linkis helpful

这个片段链接很有帮助

Also can use send_from_directoryif you want send file from certain directory:

send_from_directory如果您想从某个目录发送文件,也可以使用:

from flask import send_from_directory, current_app as app

@app.route('/show/PDFs/')
def send_pdf():
    return send_from_directory(app.config['UPLOAD_FOLDER'], 'file.pdf')

read moreabout send_from_directory

阅读更多关于send_from_directory

回答by Mwspencer

If your trying to do your typical

如果你试图做你的典型

<a href="path/doc.pdf">My Resume</a> 

where the user clicks on the link and the pdf is downloaded, you need to put your documents in your static folder.

在用户单击链接并下载 pdf 的地方,您需要将文档放在静态文件夹中。

then you end up with something like:

然后你最终会得到类似的东西:

<a href="../static/doc.pdf">My Resume</a>

回答by Rusca8

I know it's quite late, but I just found the easiest way and it's not among those.

我知道现在已经很晚了,但我刚刚找到了最简单的方法,但它不在其中。

Just redirect to the file's pathas a static file, with any hyperlink:

只需将文件作为静态文件重定向到文件路径,并带有任何超链接:

"/docs/sample.pdf" #the browser will take care about showing it

Or, if you want a maybe cleaner way... I just made a flask page for the pdfs like this:

或者,如果你想要一种更简洁的方式......我只是为这样的 pdf 制作了一个烧瓶页面:

@app.route('/pdf/') #the url you'll send the user to when he wants the pdf
def pdfviewer():
    return redirect("/docs/sample.pdf") #the pdf itself

...which I guess is kinda like giving a variable name to the pdf link (?), and also should be easier to adapt if I need to send the user to different pdfs depending on a variable.

...我想这有点像给 pdf 链接(?)一个变量名,如果我需要根据变量将用户发送到不同的 pdf,也应该更容易适应。

I'm thinking something in this lines:

我在想这几行:

@app.route('/pdf<number>') #passing variable through the url
def pdfviewer(number):
    if number == 1: #pdf depending on that variable
        return redirect("/docs/sample1.pdf")
    elif number == 2:
        return redirect("/docs/sample1.pdf")
    ...
    else:
        return "Hey I don't have such pdf" #basic html page as default

BTW: I'm working on pythonAnywhere, so I had to first define the path to the static filesin the Web tab, so I could show static files to the user.

顺便说一句:我正在使用 pythonAnywhere,所以我必须首先static files在 Web 选项卡中定义 的路径,以便我可以向用户显示静态文件。