maciej.o
maciej.o

Reputation: 187

How to download more than one file in Streamlit

I need to make a download button for more than one file. Streamlit's download button doesn't let you download more than one file. I tried to make a few buttons, but the rest just disappear when I click the first one. Is there any way to download two or more files in Streamlit?

I tried this solution from Github, this is what the code looks like:

if st.button("Rozpocznij proces"):
    raport2 = Raport.raport_naj_10(gender,year,week,engine)
    raportM = raport2[0]
    raportO = raport2[1]
    st.dataframe(raportM)
    st.dataframe(raportO)
    zipObj = ZipFile("sample.zip", "w")
    # Add multiple files to the zip
    zipObj.write("raportM")
    zipObj.write("raportO")
    # close the Zip File
    zipObj.close()

    ZipfileDotZip = "sample.zip"

    with open(ZipfileDotZip, "rb") as f:
        bytes = f.read()
        b64 = base64.b64encode(bytes).decode()
        href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
            Click last model weights\
        </a>"
    st.sidebar.markdown(href, unsafe_allow_html=True)

But I get this error:

FileNotFoundError: [WinError 2] Nie można odnaleźć określonego pliku: 'raportM'

It says that can't find the file named "raportM".

Upvotes: 1

Views: 1275

Answers (1)

Jamiu S.
Jamiu S.

Reputation: 5731

You are having those errors because the code is written with an assumption that you already have the files stored and you want to generate a zip file for them. zipObj.write("raportM") is looking for the file named "raportM" and there isn't any, because in your case you do not have these files stored. I can see that you are passing variable names as files and that is not going to work.

What you will have to do is to save those variable names as CSV files in your local machine before doing the above operations.

In this case lets modify your code. But before that we need to initialize a session state for the button st.button("Rozpocznij proces") because streamlit button have no callbacks.

processbtn = st.button("Rozpocznij proces")
# Initialized session states
if "processbtn_state" not in st.session_state:
    st.session_state.processbtn_state = False

if processbtn or st.session_state.processbtn_state:
    st.session_state.processbtn_state = True

    raport2 = Raport.raport_naj_10(gender,year,week,engine)
    raportM = raport2[0]
    raportO = raport2[1]
    st.dataframe(raportM)
    st.dataframe(raportO)

    # Save files
    raportM.to_csv('raportM.csv') # You can specify a directory where you want
    raportO.to_csv('raportO.csv') # these files to be stored

    # Create a zip folder
    zipObj = ZipFile("sample.zip", "w")

    # Add multiple files to the zip
    zipObj.write("raportM.csv")
    zipObj.write("raportO.csv")
    # close the Zip File
    zipObj.close()

    ZipfileDotZip = "sample.zip"

    with open(ZipfileDotZip, "rb") as f:
        bytes = f.read()
        b64 = base64.b64encode(bytes).decode()
        href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
            Click last model weights\
        </a>"
    st.sidebar.markdown(href, unsafe_allow_html=True)

At this moment, when you pay close attention to your directories you will find 'raportM.csv' and 'raportO.csv' files. You can pass a condition to the download button so that whenever a download is made the files should be deleted in case you don't want to keep them.

Note: You may encounter fileNotFound Error but does not mean that it won't work, you will just need to know where you are saving the files.

Upvotes: 0

Related Questions