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

前端 未结 2 1481
无人及你
无人及你 2021-01-28 19:40

I am using a Flask Code with the following route:

@app.route(\'/download\')
def download_file():
    path = \"certificate.docx\"
    print(\"certificate printed\         


        
相关标签:
2条回答
  • 2021-01-28 20:05

    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:


    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:

    0 讨论(0)
  • 2021-01-28 20:07

    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.
    0 讨论(0)
提交回复
热议问题