You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 03:49:54