如何在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
相关产品推荐
相关产品推荐

