How to create a donwload Button

Hi everyone, i’m looking for something to able the user download a dataframe at my app. So when he hits the button named “Download the Dataframe” the app will automatically donwload a specific dataframe.

I tried this code below, which also found at streamlit forum (i dont’ rememer the author) but didn’t worked. When i click to download the dataframe the app returns to the main page…

def download_link(object_to_download, download_filename, download_link_text):
    """
    Generates a link to download the given object_to_download.

    object_to_download (str, pd.DataFrame):  The object to be downloaded.
    download_filename (str): filename and extension of file. e.g. mydata.csv, some_txt_output.txt
    download_link_text (str): Text to display for download link.

    Examples:
    download_link(YOUR_DF, 'YOUR_DF.csv', 'Click here to download data!')
    download_link(YOUR_STRING, 'YOUR_STRING.txt', 'Click here to download your text!')

    """
    if isinstance(object_to_download,pd.DataFrame):
        object_to_download = object_to_download.to_csv(index=False)

    # some strings <-> bytes conversions necessary here
    b64 = base64.b64encode(object_to_download.encode()).decode()

    return f'<a href="data:file/txt;base64,{b64}" download="{download_filename}">{download_link_text}</a>'

and here there is the donwload button:

if st.button("Download the Cg  Spreedsheet"):

            tmp_download_link = download_link(df4, 'cg_result.csv', 'Click here to download your data!')

            st.markdown(tmp_download_link, unsafe_allow_html=True)

a complete code example is like this:

import base64
import json
import pickle
import uuid
import re

import streamlit as st
import pandas as pd

def download_button(object_to_download, download_filename, button_text, pickle_it=False):

if pickle_it:
    try:
        object_to_download = pickle.dumps(object_to_download)
    except pickle.PicklingError as e:
        st.write(e)
        return None

else:
    if isinstance(object_to_download, bytes):
        pass
    
    elif isinstance(object_to_download, pd.DataFrame):
        object_to_download = object_to_download.to_csv(index=False)
    
    # Try JSON encode for everything else
    else:
        object_to_download = json.dumps(object_to_download)

try:
    # some strings <-> bytes conversions necessary here
    b64 = base64.b64encode(object_to_download.encode()).decode()

except AttributeError as e:
    b64 = base64.b64encode(object_to_download).decode()

button_uuid = str(uuid.uuid4()).replace('-', '')
button_id = re.sub('\d+', '', button_uuid)

prim_color =#F43365
bg_color = #000000
sbg_color = #f1f3f6
txt_color = #000000
font = sans serif


custom_css = f"""
    <style>
        #{button_id} {{
            background-color: {bg_color};
            color: {txt_color};
            padding: 0.25rem 0.75rem;
            position: relative;
            line-height: 1.6;
            border-radius: 0.25rem;
            border-width: 1px;
            border-style: solid;
            border-color: {bg_color};
            border-image: initial;
            filter: brightness(105%);
            justify-content: center;
            margin: 0px;
            width: auto;
            appearance: button;
            display: inline-flex;
            family-font: {font};
            font-weight: 400;
            letter-spacing: normal;
            word-spacing: normal;
            text-align: center;
            text-rendering: auto;
            text-transform: none;
            text-indent: 0px;
            text-shadow: none;
            text-decoration: none;
        }}
        #{button_id}:hover {{
            
            border-color: {prim_color};
            color: {prim_color};
        }}
        #{button_id}:active {{
            box-shadow: none;
            background-color: {prim_color};
            color: {sbg_color};
            }}
    </style> """

dl_link = custom_css + f'<a download="{download_filename}" class= "" id="{button_id}" ' \
                       f'href="data:file/txt;base64,{b64}">{button_text}</a><br></br>'

return dl_link

tmp_download_link = download_button(df, f’{“example”}.csv’,‘Click here to download your csv!’,pickle_it=Fasle)

st.markdown(tmp_download_link, unsafe_allow_html=True)

df is your dataframe object, such as df=pd.read_csv(“example.csv”) or pd.DataFrame(list)

Nice, if possible, try to insert all algorithm between exemplo gonna be better to understand what you trying to say and also check the grammar and sintax. BTW your code didn’t worked!

Here it’s your code:

import base64
import json
import pickle
import uuid
import re

import streamlit as st
import pandas as pd

def download_button(object_to_download, download_filename, button_text, pickle_it=False):

    if pickle_it:
        try:
            object_to_download = pickle.dumps(object_to_download)
        except pickle.PicklingError as e:
            st.write(e)
        return None

    else:
        if isinstance(object_to_download, bytes):
            pass
    
        elif isinstance(object_to_download, pd.DataFrame):
            object_to_download = object_to_download.to_csv(index=False)
    
    # Try JSON encode for everything else
        else:
            object_to_download = json.dumps(object_to_download)

    try:
    # some strings <-> bytes conversions necessary here
        b64 = base64.b64encode(object_to_download.encode()).decode()

    except AttributeError as e:
        b64 = base64.b64encode(object_to_download).decode()

    button_uuid = str(uuid.uuid4()).replace('-', '')
    button_id = re.sub('\d+', '', button_uuid)

    prim_color = #F43365
    bg_color =  #000000
    sbg_color = #f1f3f6
    txt_color = #000000
    font = sans-serif


    custom_css = f"""
        <style>
            #{button_id} {{
                background-color: {bg_color};
                color: {txt_color};
                padding: 0.25rem 0.75rem;
                position: relative;
                line-height: 1.6;
                border-radius: 0.25rem;
                border-width: 1px;
                border-style: solid;
                border-color: {bg_color};
                border-image: initial;
                filter: brightness(105%);
                justify-content: center;
                margin: 0px;
                width: auto;
                appearance: button;
                display: inline-flex;
                family-font: {font};
                font-weight: 400;
                letter-spacing: normal;
                word-spacing: normal;
                text-align: center;
                text-rendering: auto;
                text-transform: none;
                text-indent: 0px;
                text-shadow: none;
                text-decoration: none;
        }}
        #{button_id}:hover {{
            
            border-color: {prim_color};
            color: {prim_color};
        }}
        #{button_id}:active {{
            box-shadow: none;
            background-color: {prim_color};
            color: {sbg_color};
            }}
    </style> """

    dl_link = custom_css + f'<a download="{download_filename}" class= "" id="{button_id}" ' \
                       f'href="data:file/txt;base64,{b64}">{button_text}</a><br></br>'

    return dl_link

if st.button("Download the Cg  Spreedsheet"):
      tmp_download_link = download_link(df4, 'cg_result.csv', 'Click here to download your data!')
      st.markdown(tmp_download_link, unsafe_allow_html=True)

and there are bunch of mystakes in this part. Python interpret this as a comment:

prim_color = #F43365
    bg_color =  #000000
    sbg_color = #f1f3f6
    txt_color = #000000
    font = sans-serif

The solution for this problem is posted at how-to-download-file-in-streamlit

you also can remove prim_color, bg_color…
and replace prim_color with #F43365 in code

1 Like