在 returns `send_file` 的 flask 函数中,代码不会在后续请求中出现 运行,但文件仍在下载。为什么?

In a flask function which returns `send_file`, the code doesn't appear to run on subsequent requests, yet the file still downloads. Why?

我正在使用具有以下路径的 Flask 代码:

@app.route('/download')
def download_file():
    path = "certificate.docx"
    print("certificate printed")
    print(os.getcwd())
    return send_file(path, as_attachment=True)

HTML代码:

<p>
<a href="{{ url_for('.download_file') }}">Download</a>
</p>

正在执行这段代码以下载名为 certificate.docx.

的文件

问题是函数 download_file() 中的打印语句实际上并没有被执行,但它仍然允许我下载文件。

我假设您希望打印语句显示在您的 HTML 中。如果这不是您要找的,我深表歉意。

首先,您的示例中 print 所做的是在服务器上输出文本,因此文本永远不会发送到您的 HTML。

要向您的 HTML 发送消息,您可以从 Flask 导入 flashflash 函数将向您的 HTML 发送一条消息,您可以在其中使用 get_flashed_messages().

接收代码

例子

这是改编自 Flask Docs 的示例。

下面我们做一些事情。

  1. 我们使用 flash 而不是 print。传递给 flash 的第一个参数是消息。 ("certificate printed" or os.getcwd()) 第二个参数是消息的类别。 ( "download_file") 注意类别可以完全任意,只要在模板中使用相同的类别即可。
  2. 在 HTML 中的 link 下方。我们调用get_flashed_messages并将其赋值给一个变量download_msgs。本例中唯一的参数是 category_filter=["download_file"]。这将获取我们之前使用 flash 发送的所有消息,并仅保留具有 "download_file" 类别的消息。
  3. 我们用 {% if download_msgs %} 检查消息,用 {% for message in download_msgs %} 循环消息,并显示每条消息。

烧瓶:

from flask import Flask, flash, send_file

app = Flask(__name__)

@app.route('/download')
def download_file():
    path = "certificate.docx"
    flash("certificate printed", "download_file")
    flash(os.getcwd(), "download_file")
    return send_file(path, as_attachment=True)

HTML:

<p>
  <a href="{{ url_for('.download_file') }}">Download</a>

  {% with download_msgs = get_flashed_messages(category_filter=["download_file"]) %}
    {% if download_msgs %}
      <ul class=flashes>
      {% for message in download_msgs %}
        <li>{{ message }}</li>
      {% endfor %}
      </ul>
    {% endif %}
  {% endwith %}
</p>

这个例子很粗糙,但我希望它能回答你的问题

总结

  • 要从您的 Flask 应用向您的 HTML 代码发送消息,您可以使用 Flask 应用中的 flash 功能。
  • 要从您的 Flask 应用接收消息到您的 HTML 代码,您可以在 HTML 代码中使用 get_flashed_messages 函数。
  • 您可以使用类别来区分闪烁的消息。在你的烧瓶应用程序中使用 flash 的第二个参数。在 HTML 代码中使用 get_flashed_messagescategory_filter 关键字参数。

这个问题很可能是由 Flask 内置的缓存引起的。这设置了 Cache-Control header,并适用于 Flask 提供的静态文件,也适用于 send_filesend_from_directory 函数。 (reference).

这将解释文件下载的行为,但打印语句不是 运行。事实上,该请求甚至不会到达服务器。

您可以在开发工具的网络选项卡上将其可视化:


您可以通过在您的应用中设置以下配置变量来禁用此功能:

app.config['SEND_FILE_MAX_AGE_DEFAULT'] = -1

-1 值禁用缓存。

您可能必须实际清除浏览器缓存才能使此设置生效,或者更改 /download 端点的 URL,尽管这很不方便。

设置后请注意区别: