简体   繁体   中英

download csv file in Dash

I am building an app with Dash plotly, and the app has the option to save a csv file (that create during the running time of the app), but I have problem with saving the csv file.

What I was trying to do is to use html.A component, and set the href attribute with this data:

csv_string = df.to_csv(encoding='utf-8', index=True)
csv_string = "data:text/csv;charset=utf-8," + urllib.parse.quote(csv_string)

the csv_string is the data I assigned to href attribute. I saw someone recommended on this approach, and it's really seems to work.

The problem appeared when the Data frame is too big. When this happened there is a download error when trying to save the file.

  1. Do you think I classified the problem correctly? Is it really possible to be a size problem?

  2. What do you think I can do to fix this problem? is there any other solution for saving the file? I need to say that I don't want to download the file to static folder. I need to have solution that download the file to the default download folder of the user or enable the user to have the option to select the folder he would like to save the file into (with windows that pop up maybe).

Edit: I found this link: http://chandrewz.github.io/blog/downloading-large-csv-files-via-href that describe exactly the problem I have. Is there a solution similar to what the author suggest in Python?

The Download component from the dash-extensions package performs the download action using Blob, so it might solve your issue. Here is a small example,

import dash
import dash_html_components as html
import numpy as np
import pandas as pd

from dash.dependencies import Output, Input
from dash_extensions import Download
from dash_extensions.snippets import send_data_frame

# Generate some example data.
data = np.column_stack((np.arange(10), np.arange(10) * 2))
df = pd.DataFrame(columns=["a column", "another column"], data=data)
# Create app.
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([html.Button("Download csv", id="btn"), Download(id="download")])

@app.callback(Output("download", "data"), [Input("btn", "n_clicks")])
def generate_csv(n_nlicks):
    return send_data_frame(df.to_csv, filename="some_name.csv")

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

If you decide to try it out, you can install the package via pip

pip install dash-extensions==0.0.18

Disclaimer: I am the author of Dash Extensions.

EDIT: As per Dash 1.20.0 the Download component has been merged into dash-core-components . The above example can thus be rewritten without the use of any third-party libraries,

import dash
import dash_html_components as html
import dash_core_components as dcc
import numpy as np
import pandas as pd
from dash.dependencies import Output, Input

# Generate some example data.
data = np.column_stack((np.arange(10), np.arange(10) * 2))
df = pd.DataFrame(columns=["a column", "another column"], data=data)
# Create app.
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([html.Button("Download csv", id="btn"), dcc.Download(id="download")])

@app.callback(Output("download", "data"), [Input("btn", "n_clicks")])
def generate_csv(n_nlicks):
    return dcc.send_data_frame(df.to_csv, filename="some_name.csv")

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

Here's how I allowed downloading a CSV file with the Dash framework, with no extra libraries required:

from flask import request, Response
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd

# This is in the Dash app layout
# Using Bootstrap class for nice styling
html.A(
    "Download CSV",
    id="download_csv",
    href="#",
    className="btn btn-outline-secondary btn-sm"
)


@app.callback(
    Output('download_csv', 'href'),
    [Input('some_input', 'value')]
)
def some_callback(input_value):
    """Some callback that updates the href for the button"""
    
    return f"/download_csv?value={input_value}"


@app.route('/download_csv')
def dash_download_csv():
    """Regular Flask route.
    Download a CSV file from an existing Pandas DataFrame"""

    # Here's the argument passed to the URL in the Dash callback
    value = request.args.get('value')
    df = get_df(value)
    
    # Convert DataFrame to CSV
    csv = df.to_csv(index=False)

    return Response(
        csv,
        mimetype="text/csv",
        headers={
            "Content-disposition": "attachment; filename=rcom_data.csv"
        }
    )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM