Streamlit download_button下载Zip文件失败,报错RuntimeError求助
问题描述
从.xlsx文件中的URL下载图片并打包为Zip文件,单独执行打包代码正常,但使用Streamlit的download_button时触发错误:
RuntimeError: Invalid binary data format: <class 'zipfile.ZipFile'>
相关代码如下:
import pandas as pd import urllib.request import zipfile df = pd.read_excel("images.xlsx") # Column containing the image names title = df["Name"].tolist() # Column containing the image urls images = df["Image"].tolist() with zipfile.ZipFile("images.zip", "w", zipfile.ZIP_DEFLATED) as z: for idx,image in enumerate(images): response = urllib.request.urlopen(image) img_data = response.read() z.writestr(title[idx], img_data) st.download_button( label="Download Images", data=z, file_name="images.zip", mime="application/zip", )
错误原因
Streamlit的download_button的data参数要求传入二进制数据(bytes类型),而不是zipfile.ZipFile对象。直接将ZipFile实例传给data会触发格式错误。
解决方案
有两种可行的修正方式:
方式1:读取本地Zip文件的二进制内容
先完成本地Zip文件的写入,再读取其二进制数据传给download_button:
import pandas as pd import urllib.request import zipfile import streamlit as st df = pd.read_excel("images.xlsx") title = df["Name"].tolist() images = df["Image"].tolist() # 先创建本地Zip文件 with zipfile.ZipFile("images.zip", "w", zipfile.ZIP_DEFLATED) as z: for idx, image in enumerate(images): response = urllib.request.urlopen(image) img_data = response.read() z.writestr(title[idx], img_data) # 读取Zip文件的二进制内容 with open("images.zip", "rb") as f: zip_data = f.read() # 传递二进制数据给download_button st.download_button( label="Download Images", data=zip_data, file_name="images.zip", mime="application/zip", )
方式2:使用内存中的BytesIO创建Zip(推荐)
无需写入本地文件,直接在内存中生成Zip的二进制数据,更高效:
import pandas as pd import urllib.request import zipfile import streamlit as st from io import BytesIO df = pd.read_excel("images.xlsx") title = df["Name"].tolist() images = df["Image"].tolist() # 使用BytesIO在内存中创建Zip zip_buffer = BytesIO() with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as z: for idx, image in enumerate(images): response = urllib.request.urlopen(image) img_data = response.read() z.writestr(title[idx], img_data) # 将缓冲区指针移到开头,读取二进制数据 zip_buffer.seek(0) st.download_button( label="Download Images", data=zip_buffer, file_name="images.zip", mime="application/zip", )
内容的提问来源于stack exchange,提问作者d1p3n
相关产品推荐
相关产品推荐

