How to download file in streamlit

Yeah Iโ€™m trying to find a way to include a download button for a pdf using Streamlit too.

1 Like

Thank you so much for the solution! Is there any way we can download zip files? In that case, we can just compress all the stuff before downloading it and do not need to specify any format. Thanks!

Hey @wshuyi, welcome to the community.

I remember downloading a zip folder has been covered here :wink: : How to download local folder?

Fanilo

4 Likes

Thank you so much for the reply, Fanilo! :slight_smile:

1 Like

Iโ€™m still not able to download the image. What exactly is the object predicted_img? I tried inputting a wordcloud and a axessubplot, none of them worked.

1 Like

I wrote a generic downloader that should work for any type of file thatโ€™s stored on your disk.
Though some developers may whine that this is not the right/optimal thing to do, well, who cares :wink:
So here you go.

The function:

import os
import base64
def get_binary_file_downloader_html(bin_file, file_label='File'):
    with open(bin_file, 'rb') as f:
        data = f.read()
    bin_str = base64.b64encode(data).decode()
    href = f'<a href="data:application/octet-stream;base64,{bin_str}" download="{os.path.basename(bin_file)}">Download {file_label}</a>'
    return href

Usage:

st.markdown(get_binary_file_downloader_html('photo.jpg', 'Picture'), unsafe_allow_html=True)
st.markdown(get_binary_file_downloader_html('data.csv', 'My Data'), unsafe_allow_html=True)
st.markdown(get_binary_file_downloader_html('2g1c.mp4', 'Video'), unsafe_allow_html=True)
18 Likes

hi!

I get runtime error when Iโ€™m trying to download csv over 50 mb. Please help

1 Like

Worked for me. Thanks a lot!

3 Likes

Hello GokulNC, this is a very nice job. I was wondering if your code could work for downloading a power point file ? Do you have any idea ? Thank you !

Yes ofcourse. It should work for any filetype.
But for large static files (say above 50MB), it might be better to upload it somewhere online and link it.

2 Likes

I use minio for such big downloads task, upload the file from streamlit to minio and add a hyperlink to it in your app. In addition you can use presigned objects with expiration time to make your download links more secure.

3 Likes

Super, Iโ€™ll try it and let you know how it goes.

Hi, can u get an example, please)


def get_minio_link(buffer, filename, content_type, bucket_name):
    minio_client.put_object(
        bucket_name,
        filename,
        data=buffer,
        length=len(buffer.getvalue()),
        content_type=content_type,
    )
    download_url = minio_client.presigned_get_object(
                                       bucket_name,
                                       filename)
    return download_url

You can use it like this


csv_bytes = df.to_csv().encode("utf-8")

csv_buffer = BytesIO(csv_bytes)

filename = "mydf.csv"

content_type = "application/csv"

uri = get_minio_link(buffer=csv_buffer, filename=filename, content_type=content_type, bucket_name="my-bucket")

st.markdown(
    f"""
    <a href='{uri}' download>Click to Download {filename}</a>
    """,
    unsafe_allow_html=True,
)

Its untested but it should work if you feed a proper minio_client.

Psst. by default link will be available for 7 days. I would change expire to something less. https://docs.min.io/docs/python-client-api-reference.html#presigned_get_object

Hope it helps ! :slight_smile:

5 Likes

It worked for me with a PDF file. Thanks!

1 Like

great!!! thanks very much!!

You can return this HTML to display a button instead of a link:

return f'<a href="data:file/txt;base64,{b64}" download="{download_filename}"><input type="button" value="Download"></a>'
1 Like

Hi @sgoede,

I think you can try something with minio if you want more control over the file access. Refer to this answer, How to download file in streamlit

Hope it helps!

Hi @Bernardo_tod,
Iโ€™m using the same function. If i click the link that has been generated and displayed through markdown. the file not getting downloaded. can you help me with it?

Hi @Chad_Mitchell , thanks for the solution. It works great on my Windows 10 machine. I uploaded the script to a Ubuntu 16.04 server, but the text file I download has encoded base64 characters. Something like this:

"ZW1wbG95ZXIgcGxhbgpncmFuZGZhdGhlcmVkIGhlYWx0aCBwbGFuCm5ldyBjZW50ZXIgc3RhbXBpbmcKdG90YWwgaGVhbHRoIGNhcmUKcGxhbiBhZG1pbmlzdHJhdG9yCmh"

Any idea how I can download normal text? Not sure why it is happening only on my server though. Thanks in advance for your support!

Update:

I fixed it by making this change:

from

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

to

return f'<a href="data:text/plain;base6 4,{object_to_download}" download="{download_filename}">{download_link_text}</a>'

1 Like