2025年5月24日 星期六

Streamlit 學習筆記 : 使用者輸入元件 (十五) 檔案下載按鈕

本篇旨在測試 Streamlit 的檔案下載按鈕函式 st.download_button().

本系列所有測試文章參考 :


呼叫 st.download_button() 函式並傳入必要參數 label 與 data 會建立一個檔案下載按鈕, 按下按鈕可下載 data 參數之資料, 其參數結構如下 : 

st.download_button(label, data, file_name=None, mime=None, key=None, help=None, on_click=None, args=None, kwargs=None, disabled=False, use_container_width=False)

st.download_button() 傳回值為 True (有按下按鈕) 或 False (沒按按鈕). 
 
參數說明如下表 :


st.download_button() 參數 說明
label 按鈕上顯示的文字
data 要下載的資料,可以是 bytes、str、或檔案物件(如 BytesIO)
file_name 使用者下載時的檔名,若未提供,瀏覽器會使用預設名稱
mime MIME 類型(例如 "text/csv"、"application/pdf")
key 元件的唯一識別鍵,避免重複時出錯
help 滑鼠懸停時顯示的提示文字
on_click 按下按鈕時呼叫的函式
args 傳遞給 on_click 函式的非關鍵字參數 (tuple)
kwargs 傳遞給 on_click 函式的關鍵字參數 (dict)
disabled 若為 True,按鈕將被停用
use_container_width 若為 True,按鈕會撐滿容器寬度


其中的 mime 參數為與 data 資料內容對應之檔案類型, 若未指定則 Streamlit 會根據 file_name 參數的副檔名推斷後自動指定. 但為了避免誤判, 也為了下載時瀏覽器能正確識別檔案格式, 最好還是自行指定正確的 MIME 類型 (特別是二進位資料) 為宜.  

常用的 MIME 類型如下表 : 


 MIME 類型  說明
text/plain 一般純文字檔(如 .txt)
text/csv CSV 檔案(如 .csv)
text/html HTML 檔案
application/json JSON 檔案
application/pdf PDF 文件
application/xml XML 資料
application/vnd.ms-excel Excel 檔(.xls,舊版格式)
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Excel 檔(.xlsx,新版格式)
application/zip ZIP 壓縮檔
image/png PNG 圖片
image/jpeg JPEG 圖片
image/svg+xml SVG 向量圖
image/gif GIF 動圖
audio/mpeg MP3 音訊
audio/wav WAV 音訊
video/mp4 MP4 影片


例如 : 


測試 1 : 下載文字檔 [看原始碼]   

# st-download_button-test-1.py
import streamlit as st

text='Hello World!'
download=st.download_button(
    label='下載文字檔',
    data=text,
    file_name='hello.txt',
    mime='text/plain'
    )
if download:
    st.write('檔案已下載')

結果如下 : 




也可以用 open() 開啟任何檔案, 然後設定正確之 MIME 類型, 下面是下載本機 PDF 檔的範例 :


測試 2 : 下載 PDF 檔 [看原始碼]   

# st-download_button-test-2.py
import streamlit as st

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf'
    )

此例先用 open() 開啟本機目錄下的 PDF 檔為 Bytes 類型資料, 將 mime 參數設為 application/pdf 即可正確下載, 結果如下 : 




下面範例測試 on_click 與 args 參數的用法 :


測試 3 : 參數 on_click 與 args 用法 [看原始碼]   

# st-download_button-test-3.py
import streamlit as st

def on_click_download(original, downloaded):
    st.write(f'檔案 {original} 已被下載為 {downloaded}')

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf',
    on_click=on_click_download,
    args=('sample.pdf', 'downloaded_sample.pdf')    
    )

由於 st.download_button() 傳回 True/False, 故此例沒有設定 key 來取得傳回值. 按下按鈕時會將 args 的兩個引數傳遞給 on_click 事件處理函式的 original 與 downloaded 參數, 結果如下 : 




此例也可以用 kwargs 參數來做, 例如 : 


測試 4 : 參數 on_click 與 kwargs 用法 [看原始碼]   

# st-download_button-test-4.py
import streamlit as st

def on_click_download(original, downloaded):
    st.write(f'檔案 {original} 已被下載為 {downloaded}')

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf',
    on_click=on_click_download,
    kwargs={'original': 'sample.pdf', 'downloaded': 'downloaded_sample.pdf'}    
    )

此例改用 kwargs 字典來傳遞兩個引數, 結果與上例相同. 

沒有留言 :