How to programmatically detect if I have clicked the cross button to drop the uploaded file in the file_uploader() widget?

Below is the image of my file_uploader() widget with an uploaded pdf file. I want to know how can I programmatically detect or validate I have successfully dropped/removed the uploaded file when I clicked on the Cross Button ?
image

@mingjun1120

You could check with a condition if the uploaded file is actually uploaded or not with is None or is not None which has the same end result as your question on if pressing the Cross Button. You do not need to know if user pressed the Cross-Button, just if user has an uploaded file or not logically.

uploaded_file = st.file_uploader( 
                                 label = "Upload your file", 
                                 type = ["csv", "xls", "xlsx", "xlsm", "xlsb"], 
                                 accept_multiple_files = False, 
                                 label_visibility = 'collapsed'
                                 )
                                         
# IF no file is uploaded                                        
if uploaded_file is None
 # show user message
 st.write('please upload your file')
else:
  # ELSE run code e.g. if file is uploaded
  st.write('your file has uploaded succesfully')

see official documentation: st.file_uploader - Streamlit Docs

Mark this as solution if this worked! Else let me know…

1 Like

What I mean is if I click on the cross bar, how can I detect the uploaded file is dropped? I know how to detect if the file is uploaded.

@mingjun1120

I do not know your use-case, but I can think of the below solution.

I provided an example with setting persistent session states versus Streamlit temporary session state that only keeps it in memory if you do not switch pages or keep widget in sidebar. Therefore I use custom package from Mr-Milk: GitHub - Mr-Milk/streamlit-fire-state: Persist page state for multipage streamlit app

My example displays a message when user pressed the Cross Button.

# import required packages
import streamlit as st
from fire_state import create_store, form_update, get_state, set_state, get_store, set_store

# see variables kept in session state
st.write(st.session_state)

# title
st.title('Hi, Welcome to Streamlit Demo')

# set default value to None persistent in memory
create_store("MY_SLOT", [
("uploaded_file_value1", None),
])
   
uploaded_file = st.file_uploader("Upload your file", 
                                 type=["csv", "xls", "xlsx", "xlsm", "xlsb"], 
                                 accept_multiple_files=False, 
                                 label_visibility='collapsed',
                                 )

# if file is not uploaded anymore and previously it was uploaded -> then x button must have been clicked
if uploaded_file == None and get_state("MY_SLOT", "uploaded_file_value1") != None:
    st.write('you pressed the cross button! RUN YOUR OTHER CODE BELOW!')

# update session state value to value of uploaded_file
set_state("MY_SLOT",  ("uploaded_file_value1", uploaded_file))

Let me know if this helps your use-case.

Can you explain this line of code? I can’t get it!
get_state("MY_SLOT", "uploaded_file_value1") != None

I just know the uploaded_file_value1 is a variable in the Streamlit session state.

@mingjun1120 Let me walk you through my logic.

The custom package from Mr-Milk fire_state has a get_state() function to retrieve a session state value based on retrieving it’s associated key e.g. ’ uploaded_file_value1’ (like a dictionary). The MY_SLOT is just part of the key, but acts as a prefix: ‘MY_SLOT_NAME-KEY_NAME’ to group certain keys together more easily.

The key is ‘uploaded_file_value1’ and it’s default value is initially set to None with the create_store() function like below:

# set default value to None persistent in memory
create_store("MY_SLOT", [
("uploaded_file_value1", None),
])

In my example it checks then if the session state value of key is unequal to None:
This means the first time you start your Streamlit app i.e. Python script runs, the session state value of key ‘uploaded_file_value1’ will always default to None as no file is uploaded yet and default value with create_store() is set. However, when you upload a file, your entire Python script reruns and skips create_store() as it already finds the key in the session state, and this time it updates the session state with a value (unequal to None) because of line:

set_state(“MY_SLOT”, (“uploaded_file_value1”, uploaded_file))

When printing the session state, you can see it now is equal to in my own example:

"__MY_SLOT-uploaded_file_value1__":

"UploadedFile(id=45, name='quarterly_dummy_data.xlsx', type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', size=8978)"

The Cross-Button is only displayed when there is a file uploaded, so you check in the stored value of the session state if previously a file is uploaded (e.g. unequal to None) with:

# retrieve a variable saved in the session state and check if it is unequal to a value e.g. None
get_state("your slot name", "my_key") != None

and when the entire Python script reruns when you press the Cross-Button you check if uploaded_file is None and session state still has a value inside e.g.:

MY_SLOT-uploaded_file_value1”:

“UploadedFile(id=45, name=‘quarterly_dummy_data.xlsx’, type=‘application/vnd.openxmlformats-officedocument.spreadsheetml.sheet’, size=8978)”

Below code mimics the result of the user pressing the Cross-Button by validating if 2 conditions are met:

  1. if currently no file is present in the st.file_uploader() → in other words equals None, which I save under uploaded_file variable
  2. the previous time the Python script ran you had a file uploaded and this was saved under session state value you can retrieve with the get_state() function.
if uploaded_file == None and get_state("MY_SLOT", "uploaded_file_value1") != None:
    st.write('you pressed the cross button! RUN YOUR OTHER CODE BELOW!')

Lastly, at the end of your code you can let the script update the session state again to current value of st.file_uploader() which is None if you pressed the Cross-button - because no more file is present in the st.file_uploader():

# update session state value to value of uploaded_file
set_state("MY_SLOT",  ("uploaded_file_value1", uploaded_file))

Let me know if that clarifies it for you or you have additional questions.

1 Like

Thank you for your explanation. You really cleared up my confusion.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.