Where to save temporary file for user to download

Hey there,

where do I have to save temporary files that get created “during a session” so that the user can download it? If I throw them in my own folder the download link (with an A HTML element) can’t find it. If I save the temporary files into the assets folder my app reloads after saving.
Do you guys have a solution for that?

Thanks in advance!

You can do this by creating a flask route to handle file download requests.

Minimal Example Serve from Disk

import dash
import dash_html_components as html
import flask

app = dash.Dash(__name__)

app.layout = html.Div([
    html.A("Download", href="/downloads/data.csv",),
])

@app.server.route("/downloads/<path:path_to_file>")
def serve_file(path_to_file):

    return flask.send_file(
        "data.csv",
        as_attachment=True,
    )

if __name__ == '__main__':
    app.run_server(debug=True)

Serve a File from Memory

If you want to generate a file for a user dynamically you can modify your serve_file function to something like

import io
import pandas as pd

# Normal code here... see earlier examples

@app.server.route("/downloads/<path:path_to_file>")
def serve_file(path_to_file):

    dataframe = pd.read_csv("data.csv")

    # Do something interesting here with the data

    proxyIO = io.StringIO()
    dataframe.to_csv(proxyIO, index=False, encoding="utf-8")

    mem = io.BytesIO()
    mem.write(proxyIO.getvalue().encode("utf-8"))
    mem.seek(0)

    return flask.send_file(
        mem,
        mimetype="text/csv",
        attachment_filename=path_to_file,
        as_attachment=True,
        cache_timeout=0,
    )

Customise Using Query String

e.g. navigate to /downloads/data.csv?name=Steve

import ast

# Normal code here... see earlier examples

@app.server.route("/downloads/<path:path_to_file>")
def serve_file(path_to_file):

    query_parameters = [
        "name"
    ]

    inputs = []
    for param_name in query_parameters:
        original = flask.request.args[param_name]

        try:
            val = ast.literal_eval(original)
        except Exception:
            val = original

        inputs.append(val)

    param_dict = dict(zip(query_parameters, inputs))

    # Do something with the query parameters here
    # Generate a file

    return flask.send_file(....)
3 Likes

I just realised it’s probably safer to use parse_qsl for the last example!

1 Like