Bernardo_tod’s function to generate the excel file download link works perfectly when I run my app on the local server. However, in the online-version of the app, the link doesn’t react. Anyone have a clue why?
Remember to use return href
Exactly the same problem here. Maybe it has to do with some background packages not present on the OS of the server?
I modified an earlier result to download a file from AWS using boto3, might be useful to someone:
import boto3
import base64
import uuid
import re
def download_aws_object(bucket, key):
"""
Download an object from AWS
Example key: my/key/some_file.txt
"""
s3 = boto3.resource('s3')
obj = s3.Object(bucket, key)
file_name = key.split('/')[-1] # e.g. some_file.txt
file_type = file_name.split('.')[-1] # e.g. txt
b64 = base64.b64encode(obj.get()['Body'].read()).decode()
button_uuid = str(uuid.uuid4()).replace("-", "")
button_id = re.sub("\d+", "", button_uuid)
custom_css = f"""
<style>
#{button_id} {{
background-color: rgb(255, 255, 255);
color: rgb(38, 39, 48);
padding: 0.25em 0.38em;
position: relative;
text-decoration: none;
border-radius: 4px;
border-width: 1px;
border-style: solid;
border-color: rgb(230, 234, 241);
border-image: initial;
}}
#{button_id}:hover {{
border-color: rgb(246, 51, 102);
color: rgb(246, 51, 102);
}}
#{button_id}:active {{
box-shadow: none;
background-color: rgb(246, 51, 102);
color: white;
}}
</style> """
dl_link = (
custom_css
+ f'<a download="{file_name}" id="{button_id}" href="data:file/{file_type};base64,{b64}">Download {file_name}</a><br></br>'
)
return dl_link
st.markdown(download_aws_object(bucket, key), unsafe_allow_html=True)
A question. I am testing this code.
output = BytesIO()
st.write("checkpoint 1")
writer = pd.ExcelWriter(output, engine='xlsxwriter')
st.write("checkpoint 2")
When I running it in local, I get 2 checkpoint printed.
When I running it in Heroku, I only get the first checkpoint printed so I can’t write something to excel.
I need to write something to excel and download it from my Heroku App. Is there any solution to fix this?
Thank you
Great function, I love our community.
The download works like a charm for dataframes! However, does anyone have a solution for large dfs?
If the Excel is larger than 50MB, an error is produced. This can be avoided by changing MESSAGE_LIMIT_SIZE in site-packages/streamlit/server/server_util.py (see RuntimeError: Data of size 107.9MB exceeds write limit of 50.0MB - Using Streamlit - Streamlit).
BUT, now I get a Tornado error:
future: <Task finished coro=<WebSocketProtocol13.write_message..wrapper() done, defined at /home/argusadmin/notebooks/Datalake.NLP.Demos/.nlp_demos/lib/python3.6/site-packages/tornado/websocket.py:1100> exception=WebSocketClosedError()>
Traceback (most recent call last):
File “/home/argusadmin/notebooks/Datalake.NLP.Demos/.nlp_demos/lib/python3.6/site-packages/tornado/websocket.py”, line 1102, in wrapper
await fut
tornado.iostream.StreamClosedError: Stream is closed
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “/home/argusadmin/notebooks/Datalake.NLP.Demos/.nlp_demos/lib/python3.6/site-packages/tornado/websocket.py”, line 1104, in wrapper
raise WebSocketClosedError()
tornado.websocket.WebSocketClosedError
2021-03-08 13:46:57.248 Task exception was never retrieved
future: <Task finished coro=<WebSocketProtocol13.write_message..wrapper() done, defined at /home/argusadmin/notebooks/Datalake.NLP.Demos/.nlp_demos/lib/python3.6/site-packages/tornado/websocket.py:1100> exception=WebSocketClosedError()>
Traceback (most recent call last):
File “/home/argusadmin/notebooks/Datalake.NLP.Demos/.nlp_demos/lib/python3.6/site-packages/tornado/websocket.py”, line 1102, in wrapper
await fut
tornado.iostream.StreamClosedError: Stream is closed
I assume that this is due to Tornado’s max byte size, but I’m not sure how I could possibly adjust that from within streamlit. Any ideas?
FYI, I solved the problem by saving the dataframe in streamlit’s static folder: Ability to download data from Streamlit · Issue #400 · streamlit/streamlit (github.com)
Hi everyone, thanks for the sharing, I’m looking to download a read-only excel file from a data frame. Has anyone works on this before? Below is the current downloader. Thanks!
def to_excel(df):
output = BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1')
writer.save()
processed_data = output.getvalue()
return processed_data
def get_table_download_link(df):
"""Generates a link allowing the data in a given panda dataframe to be downloaded
in: dataframe
out: href string
"""
val = to_excel(df)
b64 = base64.b64encode(val)
return f'<a href="data:application/octet-stream;base64,{b64.decode()}" download="Your_File.xlsx">Download Excel file</a>'
I followed the suggested solution, it works fine… But i get the following error message that I cant surpress: UnhashableTypeError : Cannot hash object of type streamlit.delta_generator.DeltaGenerator
, found in something.
While caching something, Streamlit encountered an object of type streamlit.delta_generator.DeltaGenerator
, which it does not know how to hash.
To address this, please try helping Streamlit understand how to hash that type by passing the hash_funcs
argument into @st.cache
. For example:
Tried different things,but still get the same result. Can anyone help?
This works perfectly
Has anyone done this for a Parquet file, using df.to_parquet ?
Great Job! Thanks for your work!
I have upgraded this code a little bit with my friend, so it uses custom colors that you have in your streamlit app, find a snippet here:
Hello, thanks for your good job.
when I was running the function, I got a feedback
can not find theme.primaryColor
\ theme.backgroundColor
\ theme.secondaryBackgroundColor
\ theme.textColor
\ theme.font
where is these setting locating?
Hi,
first of all, this will work only for versions >=0.79.
I think your feedback suggests that you have an older version installed.
Another thing is that st.config.get_option
for theme options will return None if you don’t use a custom theme. So the easiest fix for you would be to add to your config file .streamlit/config.toml
something like this:
[theme]
# should look like a light theme
primaryColor = '#f43365'
backgroundColor = '#000000'
secondaryBackgroundColor = '#f1f3f6'
textColor = '#000000'
font = 'sans serif'
If you don’t have this file just create it in your project or home directory.
my streamlit version is 0.80, and I had added the content of you provied to config.toml
when I use this function, no download button shows.
download_button(pd.Dataframe(list), 'example.csv', 'example.csv', pickle_it=False)
when I use this function, no download button shows.
If it does not appear you should use the line with st.markdown - this is the code that you need to place:
tmp_download_link = download_button(df_to_save.reset_index(), f'{file_name}.csv',
button_text='Click here to download your text!')
st.markdown(tmp_download_link, unsafe_allow_html=True)
Did you do that?
Hi, can I replace the df_to_save.reset_index() with df or pd.DataFrame(list)?
and replace f’{file_name}.csv’ with f’{example}.csv’ ?
df, pd.DataFrame(list), example is my own setting, it can change in different conditions.
Hi,
‘df_to_save.reset_index’ should be any pd.DataFrame object
file_name should be a string. here you have f’{file_name}.csv’, and file_name is a variable that will become the name of the file
This part tell what to save, what will be the name of the file and the text on the button only:
tmp_download_link = download_button(df_to_save.reset_index(), f'{file_name}.csv',
button_text='Click here to download your text!')
This part shows the button in streamlit:
st.markdown(tmp_download_link, unsafe_allow_html=True)
The part responsible for the button itself is in the snippet.
You can clone my code and look at the files:
Hope it will help you