第11章 文件上传与文件处理
在实际应用中,文件无处不在。
用户可能想要上传:
PDF
Word 文档
电子表格
CSV 文件
图片
JSON 文件
文本文件
数据集
演示文稿
Gradio 应用可以把这些文件变成实用的工作流。
比如:
上传 PDF → 提取文本 → 生成摘要。
或者:
上传 CSV → 分析数据 → 展示表格。
再或者:
上传图片 → 进行分类 → 显示预测结果。
File 组件
最基础的文件上传组件是:
file = gr.File()
更完整的写法如下:
file = gr.File(
label="Upload your document"
)
处理上传的文件
Python 函数接收到的上传文件信息,取决于组件的配置和 Gradio 版本。
常见的做法是使用上传文件的路径。
例如:
def process_file(file):
if file is None:
return "Please upload a file."
return f"Received: {file}"
建议先检查应用实际收到的值,再决定如何处理。
限制文件类型
如果应用只支持特定的文件格式,可以相应地配置文件组件。
例如,一个文档分析应用可能只接受 PDF:
file = gr.File(
file_types=[".pdf"],
label="Upload a PDF"
)
这样可以避免用户上传应用无法处理的文件。
允许多文件上传
有些应用需要处理多个文件。
根据 Gradio 版本和组件配置,你可以启用多文件上传。
例如:
files = gr.File(
file_count="multiple",
label="Upload files"
)
此时你的函数需要处理的是一组文件,而不是单个文件。
处理文本文件
Python 标准库让文本文件的处理变得很直接。
def read_text_file(file):
if file is None:
return "No file uploaded."
with open(file.name, "r", encoding="utf-8") as f:
return f.read()
对象的具体表示形式可能有所不同,请始终确认你所安装的 Gradio 版本中组件实际返回的值。
错误处理
文件处理可能因多种原因失败。
文件可能已损坏、编码不可预期、结构不受支持、体积过大,或包含格式错误的数据。
不要假设每个上传的文件都是合法的。
例如:
def read_text_file(file):
if file is None:
return "Please upload a file."
try:
with open(file.name, "r", encoding="utf-8") as f:
return f.read()
except UnicodeDecodeError:
return "This file does not appear to be UTF-8 text."
except Exception as error:
return f"Could not process the file: {error}"
在生产环境中,不要将内部错误细节直接暴露给用户。
CSV 文件
CSV 处理是 Gradio 的常见使用场景。
使用 pandas:
import pandas as pd
def analyze_csv(file):
if file is None:
return "Please upload a CSV file."
df = pd.read_csv(file.name)
return df
可以用 gr.Dataframe 展示结果。
import gradio as gr
import pandas as pd
def analyze_csv(file):
if file is None:
return pd.DataFrame()
return pd.read_csv(file.name)
with gr.Blocks() as demo:
file = gr.File(
file_types=[".csv"],
label="Upload CSV"
)
button = gr.Button("Load Data")
table = gr.Dataframe(
label="Dataset"
)
button.click(
fn=analyze_csv,
inputs=file,
outputs=table
)
demo.launch()
这已经是一个实用的小应用了。
展示统计数据
让我们把这个 CSV 应用做得更有意思一些。
import gradio as gr
import pandas as pd
def analyze_csv(file):
if file is None:
return pd.DataFrame(), "No file uploaded."
df = pd.read_csv(file.name)
summary = (
f"Rows: {len(df)}\n"
f"Columns: {len(df.columns)}"
)
return df, summary
with gr.Blocks() as demo:
file = gr.File(
file_types=[".csv"],
label="Upload CSV"
)
button = gr.Button("Analyze")
table = gr.Dataframe(
label="Dataset"
)
summary = gr.Textbox(
label="Summary"
)
button.click(
fn=analyze_csv,
inputs=file,
outputs=[table, summary]
)
demo.launch()
现在应用同时提供数据展示和基础统计。
文件大小很重要
用户上传了文件,并不意味着应用就该不加限制地直接处理它。
大文件会占用:
内存
CPU
磁盘空间
模型 tokens
处理时间
生产环境中,务必设定合理的限制。
PDF 处理
PDF 文件在 AI 应用中非常常见。
典型流程会用到 PDF 提取库,基本模式如下:
def extract_pdf(file):
if file is None:
return ""
# Open the PDF.
# Extract text.
# Return the text.
根据具体需求,可以选择 PyMuPDF 等库。
Gradio 的核心逻辑始终不变:
File component
→ Python function
→ extracted content
→ output component
DOCX 处理
Word 文档同理,可以用 python-docx 等库来处理。
例如:
from docx import Document
def extract_docx(file):
document = Document(file.name)
paragraphs = [
paragraph.text
for paragraph in document.paragraphs
]
return "\n".join(paragraphs)
将它与以下组件关联:
file = gr.File(file_types=[".docx"])
以及:
output = gr.Textbox(lines=15)
JSON 文件
在构建开发者工具时,JSON 尤其实用。
import json
def read_json(file):
if file is None:
return {}
with open(file.name, "r", encoding="utf-8") as f:
return json.load(f)
然后:
output = gr.JSON()
就能展示结构化数据了。
文件处理流水线
一个实用的应用往往遵循这样的流水线:
上传
→ 校验
→ 提取
→ 转换
→ 分析
→ 展示
如果工作流变得难以维护,就不要把所有操作都塞进一个巨大的代码块里。
把功能拆分成独立的函数,会让应用更容易测试。
示例:CSV 清洗工具
import gradio as gr
import pandas as pd
def clean_csv(file):
if file is None:
return pd.DataFrame(), "Please upload a CSV."
df = pd.read_csv(file.name)
before = len(df)
df = df.drop_duplicates()
df = df.dropna(how="all")
after = len(df)
message = (
f"Original rows: {before}\n"
f"Rows after cleaning: {after}\n"
f"Rows removed: {before - after}"
)
return df, message
with gr.Blocks() as demo:
gr.Markdown("# CSV Cleaner")
file = gr.File(
file_types=[".csv"],
label="Upload CSV"
)
button = gr.Button("Clean Dataset")
table = gr.Dataframe(
label="Cleaned Data"
)
report = gr.Textbox(
label="Cleaning Report"
)
button.click(
fn=clean_csv,
inputs=file,
outputs=[table, report]
)
demo.launch()
这是一个真正能用的工具,而不仅仅是演示。
文件下载
有些应用不仅接收文件,还会生成文件。
比如,用户可以上传 CSV 格式的文件,清洗后,再下载清洗好的 CSV。
Gradio 支持把生成的文件作为输出返回。
Python 函数可以先保存结果:
df.to_csv("cleaned.csv", index=False)
然后把生成的文件路径返回给相应的输出组件。
文件输出的具体行为请以你安装的 Gradio 版本为准。
临时文件
应用生成文件时,要考虑存储位置和保留时长。
临时输出不应当作永久存储使用。
需要长期存储时,建议使用专门的存储服务。
安全注意事项
文件上传会带来安全风险。
不能仅凭文件经由你的界面上传就认为它安全。
根据应用场景,可考虑以下措施:
文件类型校验
文件大小限制
安全的文件命名
恶意软件扫描
受限处理
沙箱隔离
避免执行上传的代码
及时清理临时文件
当应用对外公开时,上述措施尤为重要。
切勿随意执行上传的代码
假设有人上传了一个 Python 文件,不要直接这样做:
exec(uploaded_code)
这会让上传的内容获得执行任意 Python 代码的能力。
文件上传不等于文件可信。
文件名是不可信的输入
不要直接用上传的文件名拼接 shell 命令。
避免如下写法:
import os
os.system(f"process {file.name}")
因为文件名及其他用户可控值,在没有适当防护的情况下不应拼入 shell 命令。
更好的做法是尽量避免使用 shell 执行。
动手试一试
构建一个 CSV 分析应用,要求:
接受 CSV 文件上传
展示数据集
显示行数和列数
展示列名
识别缺失值
再添加一个按钮用于删除重复行。
这是很好的练习,因为它综合了:
文件上传
pandas
多种输出形式
数据校验
Gradio events
关键要点
gr.File允许用户上传文件。尽量限制可接受的文件类型。
文件处理通常在普通的 Python 函数中完成。
CSV 文件与 pandas 搭配效果尤佳。
PDF、DOCX、JSON 及其他格式均可用 Python 库处理。
处理前应先校验上传的文件。
大文件可能引发性能问题。
上传的文件应视为不可信输入。
除非有严谨的安全设计,否则切勿执行上传的代码。