Skip to content Skip to sidebar Skip to footer

In A Flask Function Which Returns `send_file`, The Code Doesn't Appear To Run On Subsequent Requests, Yet The File Still Downloads. Why?

I am using a Flask Code with the following route: @app.route('/download') def download_file(): path = 'certificate.docx' print('certificate printed') print(os.getcwd())

Solution 1:

This problem is most likely caused by caching which is built into Flask. This sets the Cache-Control header, and applies to static files served by Flask, but also the send_file and send_from_directory functions. (reference).

This would explain the behaviour of the file downloading, but the print statements not running. In fact that request won't even be hitting the server.

You can visualise this on the network tab of the dev tools:

caching enabled


You can disable this by setting the following config variable on your app:

app.config['SEND_FILE_MAX_AGE_DEFAULT'] = -1

The -1 value disables caching.

You may have to actually clear the browser cache for this setting to take affect, or change the URL of your /download endpoint, although this is inconvenient.

Note the difference once this is set:

caching disabled.


Solution 2:

I am assuming you want the print statements to show in your HTML. I apologize if that is not what you are looking for.

First what print is doing in your example is outputting text on the server, so the text never is sent to your HTML.

To send messages to your HTML you can import flash from flask. The flash function will send a message to your HTML where you can receive code with get_flashed_messages().

Example

Here is an example adapted from the Flask Docs.

Below we do a few things.

  1. Instead of print, we use flash. The first argument passed to flash is the message. ("certificate printed" or os.getcwd()) The second argument is the category of message. ( "download_file") Note that the category can be completely arbitrary as long as the same category is used in the template.
  2. Below the link in the HTML. We call get_flashed_messages and assign it to a variable download_msgs. The only argument in this case is category_filter=["download_file"]. This will get all the messages we sent with flash earlier and keep only the ones with the "download_file" category.
  3. We check for messages with {% if download_msgs %}, loop over messages with {% for message in download_msgs %}, and display each message.

Flask:

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>

This example is crude, but I hope it answers your question

Summary

  • To send messages from your flask app to your HTML code, you can use the flash function in your flask app.
  • To receive messages from your flask app to your HTML code, you can use the get_flashed_messages function in your HTML code.
  • You can use categories to differentiate flashed messages. Use the second argument of flash in your flask app. Use the category_filter keyword argument of get_flashed_messages in your HTML code.

Post a Comment for "In A Flask Function Which Returns `send_file`, The Code Doesn't Appear To Run On Subsequent Requests, Yet The File Still Downloads. Why?"