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