Streamlit多文件上传能否保留选择顺序?支持拖拽排序吗?
解决方案:Streamlit多文件上传顺序保留与拖拽调整
一、保留文件选择时的原始顺序
Streamlit默认的st.file_uploader会对多文件按文件名字母排序,要保留用户选择的原始顺序,有两种实用方案:
方案1:逐个添加文件(完全可控)
放弃一次性多文件上传,让用户依次选择文件,通过session_state记录顺序:
import streamlit as st if "uploaded_files" not in st.session_state: st.session_state.uploaded_files = [] # 单个文件上传器 uploaded_file = st.file_uploader("添加单个文件", accept_multiple_files=False) if uploaded_file and uploaded_file not in st.session_state.uploaded_files: st.session_state.uploaded_files.append(uploaded_file) # 显示已上传文件顺序 st.subheader("已上传文件顺序") for idx, file in enumerate(st.session_state.uploaded_files): st.write(f"{idx+1}. {file.name}") # 执行拼接操作 if st.button("开始拼接"): # 按session_state内的顺序处理文件 for file in st.session_state.uploaded_files: # 此处写入你的转换与拼接逻辑 st.write(f"处理文件:{file.name}")
方案2:捕获原始选择顺序(一次性上传)
通过自定义JavaScript拦截浏览器返回的原始文件顺序,再传递给Python端:
import streamlit as st import json st.file_uploader("选择多个文件", accept_multiple_files=True, key="multi_upload") # 插入JS捕获文件选择顺序 st.markdown(""" <script> document.querySelector('input[type="file"][multiple]').addEventListener('change', function(e) { const fileNames = Array.from(e.target.files).map(f => f.name); window.sessionStorage.setItem('fileOrder', JSON.stringify(fileNames)); }); </script> """, unsafe_allow_html=True) # 获取并应用原始顺序 if st.session_state.multi_upload: # 从sessionStorage读取顺序 file_order = st.experimental_get_query_params().get('fileOrder') if file_order: file_order = json.loads(file_order[0]) # 按原始顺序重新排列文件 ordered_files = sorted(st.session_state.multi_upload, key=lambda x: file_order.index(x.name)) st.subheader("原始选择顺序的文件") for file in ordered_files: st.write(file.name)
二、拖拽调整文件顺序
如果需要让用户自由调整文件顺序,推荐使用streamlit-dnd第三方组件(无需外部链接,直接pip安装):
步骤1:安装组件
pip install streamlit-dnd
步骤2:使用示例
import streamlit as st from streamlit_dnd import st_dnd if "uploaded_files" not in st.session_state: st.session_state.uploaded_files = [] # 多文件上传 uploaded_files = st.file_uploader("选择多个文件", accept_multiple_files=True) if uploaded_files: # 去重并添加到session_state for file in uploaded_files: if file not in st.session_state.uploaded_files: st.session_state.uploaded_files.append(file) # 准备拖拽排序项 drag_items = [{"label": file.name, "value": idx} for idx, file in enumerate(st.session_state.uploaded_files)] # 渲染拖拽组件 sorted_items = st_dnd(drag_items, key="file_dnd") # 根据拖拽结果更新文件顺序 if sorted_items: st.session_state.uploaded_files = [st.session_state.uploaded_files[item["value"]] for item in sorted_items] # 显示调整后的顺序 st.subheader("当前文件顺序") for idx, file in enumerate(st.session_state.uploaded_files): st.write(f"{idx+1}. {file.name}") # 执行转换与拼接 if st.button("开始处理"): for file in st.session_state.uploaded_files: # 此处写入你的处理逻辑 st.write(f"正在处理:{file.name}")
无第三方组件替代方案(手动调整)
如果不想依赖外部组件,可通过选择框+按钮实现手动上下调整:
import streamlit as st if "uploaded_files" not in st.session_state: st.session_state.uploaded_files = [] uploaded_files = st.file_uploader("选择多个文件", accept_multiple_files=True) if uploaded_files: for file in uploaded_files: if file not in st.session_state.uploaded_files: st.session_state.uploaded_files.append(file) if st.session_state.uploaded_files: selected_idx = st.selectbox("选择要调整的文件", range(len(st.session_state.uploaded_files)), format_func=lambda x: st.session_state.uploaded_files[x].name) col1, col2 = st.columns(2) with col1: if st.button("上移") and selected_idx > 0: st.session_state.uploaded_files[selected_idx], st.session_state.uploaded_files[selected_idx-1] = st.session_state.uploaded_files[selected_idx-1], st.session_state.uploaded_files[selected_idx] with col2: if st.button("下移") and selected_idx < len(st.session_state.uploaded_files)-1: st.session_state.uploaded_files[selected_idx], st.session_state.uploaded_files[selected_idx+1] = st.session_state.uploaded_files[selected_idx+1], st.session_state.uploaded_files[selected_idx] st.subheader("调整后的顺序") for idx, file in enumerate(st.session_state.uploaded_files): st.write(f"{idx+1}. {file.name}")
内容的提问来源于stack exchange,提问作者user23590571
相关产品推荐
相关产品推荐

