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

如何在Streamlit中使用st.download_button实现多文件下载?

解决Streamlit多CSV下载按钮消失及多文件下载问题

一、修复下载按钮消失的问题

你遇到的按钮消失问题,根源是Streamlit的页面重运行机制:点击st.download_button会触发页面重新加载,而原来的下载按钮都嵌套在st.button("Rozpocznij proces")的判断块里,重新加载后该按钮的状态重置,判断条件不成立,导致按钮不再渲染。

解决方法是用st.session_state保存处理后的DataFrame,让页面重跑时仍能访问到数据:

import streamlit as st
import structure  # 你的自定义模块

# 初始化会话状态,用于保存处理后的数据
if "processed_data" not in st.session_state:
    st.session_state.processed_data = None

uploaded_files = st.file_uploader("Proszę wybrać pliki csv", accept_multiple_files=True)

# 处理数据并保存到会话状态
if st.button("Rozpocznij proces") and uploaded_files:
    st.session_state.processed_data = structure.create_structure(uploaded_files)

# 缓存CSV转换逻辑(使用新版st.cache_data替代旧版st.cache)
@st.cache_data
def convert_df(df):
    return df.to_csv().encode('utf-8')

# 当存在处理后的数据时,渲染所有下载按钮
if st.session_state.processed_data is not None:
    data1 = st.session_state.processed_data
    # 定义文件名列表,适配DataFrame数量小于5的情况
    file_info = [
        ("mlode", "mlode.csv"),
        ("lochy", "lochy.csv"),
        ("knury", "knury.csv"),
        ("rozplodowa", "rozplodowa.csv"),
        ("mag", "mag.csv")
    ]
    
    for idx, (name, filename) in enumerate(file_info[:len(data1)]):
        csv_data = convert_df(data1[idx])
        st.download_button(
            label=f"Download {name} as CSV",
            data=csv_data,
            file_name=filename
        )

二、实现多文件批量下载

Streamlit原生st.download_button不支持直接下载多个文件,但可以将所有CSV打包成ZIP文件,实现批量下载:

import io
import zipfile
import streamlit as st
import structure

# 初始化会话状态
if "processed_data" not in st.session_state:
    st.session_state.processed_data = None

uploaded_files = st.file_uploader("Proszę wybrać pliki csv", accept_multiple_files=True)

if st.button("Rozpocznij proces") and uploaded_files:
    st.session_state.processed_data = structure.create_structure(uploaded_files)

# 缓存ZIP打包逻辑
@st.cache_data
def pack_to_zip(df_list, filenames):
    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
        for df, filename in zip(df_list, filenames):
            csv_content = df.to_csv(index=False).encode('utf-8')
            zip_file.writestr(filename, csv_content)
    zip_buffer.seek(0)
    return zip_buffer

if st.session_state.processed_data is not None:
    data1 = st.session_state.processed_data
    filenames = ["mlode.csv", "lochy.csv", "knury.csv", "rozplodowa.csv", "mag.csv"][:len(data1)]
    
    # 单个文件下载按钮(同第一部分逻辑)
    for idx, (name, filename) in enumerate(zip(["mlode","lochy","knury","rozplodowa","mag"], filenames)):
        csv_data = convert_df(data1[idx])
        st.download_button(
            label=f"Download {name} as CSV",
            data=csv_data,
            file_name=filename
        )
    
    # 批量下载ZIP按钮
    zip_data = pack_to_zip(data1, filenames)
    st.download_button(
        label="Download all CSVs as ZIP",
        data=zip_data,
        file_name="all_csvs.zip",
        mime="application/zip"
    )

核心说明

  • 用st.session_state持久化处理后的数据,避免页面重跑时丢失状态
  • 用st.cache_data缓存CSV转换和ZIP打包逻辑,减少重复计算
  • 批量下载通过ZIP打包实现,兼容Streamlit的单文件下载限制

内容的提问来源于stack exchange,提问作者maciej.o

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:36:07