However, it slows down the app since my file is very large and it takes too long to save the csv file on the server side. Is there any way to directly download the filtered data from the client side itself without having to save it in a temporary folder on the server.
P.S.: I am very new to flask apps and dash, so if you could explain it in simple terms, I’d be really grateful
How large is the file? In most cases, the disk write speed is much faster than the network transfer speed, in which case writing the file to disk server side doesn’t impact performance significantly.
Where does the data come from (could you share the code)? If the data is on the server in the first place, the write operation shouldn’t take more than a few seconds.
The data is stored in memory as a global variable. The csv to be downloaded is generated from a callback and saved in a hidden div.
I was able to cut out the server part by implementing something similar to this: https://github.com/plotly/dash-recipes/blob/master/download-raw-data.py
The hidden div is client side, i.e. if you save the data there, they are sent from the server to the client for storage and back again for processing when you are accessing them in a callback. That approach will yield a bad performance for large datasets. Saving the data to disk should be much faster. It is possible to serve data from memory, which would probably be the fastest option. Here is an example, where a data frame (stored as a global variable) is served,
import io
import dash
import dash_html_components as html
import pandas as pd
from flask import Flask, send_file
df = pd.DataFrame({
'a': [1, 2, 3, 4],
'b': [2, 1, 5, 6],
'c': ['x', 'x', 'y', 'y']
})
server = Flask(__name__)
app = dash.Dash(external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css'], server=server)
app.layout = html.Div([html.A("Click me", href="/test_download")])
@server.route('/test_download')
def test_download():
# Write data to StringIO Object (in memory).
buffer = io.StringIO()
df.to_csv(buffer)
buffer.seek(0)
# Send the data directly without writing to disk.
return send_file(
buffer,
attachment_filename='test.csv',
)
if __name__ == '__main__':
app.run_server(debug=False)