当前位置: 首页 > article >正文

streamlit 文件上传保存+预览

以下是一个使用 Streamlit 实现文件上传并保存到本地的示例代码,不限制文件大小:

import streamlit as st

# 设置页面标题
st.title('文件上传与保存示例')

# 文件上传
uploaded_file = st.file_uploader("请选择文件进行上传", type=None)

# 检查是否有文件上传
if uploaded_file is not None:
    # 显示文件信息
    st.write(f"文件名: {uploaded_file.name}")
    st.write(f"文件大小: {uploaded_file.size} 字节")
    
    # 获取文件字节内容
    file_bytes = uploaded_file.read()
    
    # 将文件保存到本地
    save_path = f"./{uploaded_file.name}"
    with open(save_path, "wb") as f:
        f.write(file_bytes)
    
    st.success(f"文件已保存到: {save_path}")

代码说明:

  1. file_uploader 函数用于上传文件。type=None 表示不限制文件类型。
  2. 通过 uploaded_file.read() 获取文件的字节内容。
  3. 使用 open 以写入二进制模式 (wb) 将文件保存到本地。

这个示例没有限制文件大小,但要注意上传文件的最大尺寸可能受限于 Streamlit 默认设置或 Web 浏览器的限制。如果需要调整默认的最大上传大小,可以在 Streamlit 的配置文件(通常为 ~/.streamlit/config.toml)中修改以下参数:

[server]
maxUploadSize = 2000

maxUploadSize 的单位是 MB。

为了优化文件传输的形式,可以考虑以下几个方面:

  1. 流式读取文件

    • 直接读取整个文件可能在文件较大时造成内存问题。可以通过分块读取文件(流式处理)来减少内存压力。
  2. 显示文件传输进度

    • 在文件上传过程中显示进度条,以提升用户体验。
  3. 减少内存占用

    • 避免一次性将整个文件读取到内存,按需处理文件。

基于这些优化思路,这里给出一个改进版代码:

import streamlit as st
import os

# 设置页面标题
st.title('文件上传与保存(流式传输)示例')

# 文件上传
uploaded_file = st.file_uploader("请选择文件进行上传", type=None)

if uploaded_file is not None:
    # 显示文件信息
    st.write(f"文件名: {uploaded_file.name}")
    st.write(f"文件大小: {uploaded_file.size / (1024 * 1024):.2f} MB")

    # 设定保存路径
    save_path = f"./{uploaded_file.name}"

    # 显示进度条
    progress_bar = st.progress(0)

    # 每次读取 1 MB 数据,防止大文件占用过多内存
    chunk_size = 1024 * 1024  # 1MB
    bytes_written = 0  # 已写入的字节数

    # 打开文件并分块写入本地文件
    with open(save_path, "wb") as f:
        while True:
            # 从上传的文件中按块读取数据
            file_chunk = uploaded_file.read(chunk_size)
            if not file_chunk:
                break  # 读取完成

            # 写入到本地文件
            f.write(file_chunk)
            bytes_written += len(file_chunk)

            # 更新进度条
            progress_percent = bytes_written / uploaded_file.size
            progress_bar.progress(progress_percent)

    st.success(f"文件已成功保存到: {save_path}")
    st.write(f"总写入字节数: {bytes_written}")

改进点:

  1. 流式读取

    • 使用 uploaded_file.read(chunk_size) 按 1MB 大小逐块读取文件,避免一次性读取整个文件造成内存压力。
  2. 进度条

    • 通过 st.progress() 实现实时进度条,显示上传的进度,使用户体验更好。
  3. 减少内存压力

    • 文件以流的形式逐块处理,而不是一次性加载到内存中,适合处理较大的文件。

注意事项:

  • Streamlit 本身并不支持后台异步处理,因此进度条只是本地写入的进度,在实际的 Web 环境中,上传进度也受到网络速度影响。

为了美化 Streamlitfile_uploader 组件并将界面配置为中文展示,可以通过以下方式来进行优化:

  1. 自定义上传按钮的提示:通过 label 参数自定义上传按钮的显示文本。
  2. 使用 Streamlit 内置的 Markdown 支持,美化界面。
  3. 配置 Streamlit 为中文显示:通过 streamlit/config.toml 文件进行语言配置。

优化代码:

import streamlit as st

# 设置页面标题
st.markdown(
    """
    <h2 style='text-align: center; color: #FF6347;'>文件上传与保存</h2>
    """, 
    unsafe_allow_html=True
)

# 文件上传
uploaded_file = st.file_uploader("请上传文件", type=None)

# 检查是否有文件上传
if uploaded_file is not None:
    # 显示文件信息
    st.markdown(f"**文件名:** {uploaded_file.name}")
    st.markdown(f"**文件大小:** {uploaded_file.size / (1024 * 1024):.2f} MB")

    # 设定保存路径
    save_path = f"./{uploaded_file.name}"

    # 显示进度条
    progress_bar = st.progress(0)

    # 每次读取 1 MB 数据
    chunk_size = 1024 * 1024  # 1MB
    bytes_written = 0  # 已写入的字节数

    # 打开文件并分块写入本地文件
    with open(save_path, "wb") as f:
        while True:
            # 从上传的文件中按块读取数据
            file_chunk = uploaded_file.read(chunk_size)
            if not file_chunk:
                break  # 读取完成

            # 写入到本地文件
            f.write(file_chunk)
            bytes_written += len(file_chunk)

            # 更新进度条
            progress_percent = bytes_written / uploaded_file.size
            progress_bar.progress(progress_percent)

    st.success(f"文件已保存到: {save_path}")
    st.markdown(f"**总写入字节数:** {bytes_written}")

美化与中文配置优化点:

  1. 标题美化
    使用 st.markdown() 和 HTML 标记语言,使标题居中并自定义颜色(例如橙红色 #FF6347)。

  2. 自定义文本显示
    上传按钮的标签改为 "请上传文件",并且上传后的文件信息(如文件名和大小)用加粗显示 st.markdown()

  3. 进度条与用户反馈
    上传完成后会显示成功消息,并以加粗形式展示写入的字节数。

设置界面语言为中文:

如果你想要让 Streamlit 的界面内容(如按钮和系统提示)展示为中文,可以通过修改 Streamlit 配置文件实现。

  1. 打开或创建 ~/.streamlit/config.toml 文件。

  2. 在文件中添加或修改以下内容:

    [theme]
    primaryColor = "#FF6347"
    
    [language]
    default = "zh"
    
  3. primaryColor 是用来配置主题颜色的,调整为与页面标题一致的橙红色。

  4. language.default = "zh" 是用来将 Streamlit 的界面显示设置为中文。

这样,Streamlit 界面的默认提示和按钮都会显示为中文,同时自定义的上传界面也会更加美观。

Streamlit 中展示多层文件夹结构,并支持文件预览,可以使用以下方法:

  1. 展示文件夹结构:通过递归遍历文件夹树,构建一个嵌套的目录结构。
  2. 文件预览:根据文件类型提供不同的预览方式,如文本文件的内容、图片的显示等。

下面是一个完整的示例代码:

import os
import streamlit as st

# 设置页面标题
st.title("文件夹与文件展示和预览")

# 获取文件夹路径
root_dir = st.text_input("请输入文件夹路径", value=".")

# 递归展示文件夹结构
def display_folder_structure(folder, level=0):
    for item in os.listdir(folder):
        item_path = os.path.join(folder, item)
        if os.path.isdir(item_path):
            # 显示文件夹名并递归显示其子文件夹
            st.markdown(f"{'  ' * level}📂 **{item}**")
            display_folder_structure(item_path, level + 1)
        else:
            # 显示文件名并添加文件预览按钮
            st.markdown(f"{'  ' * level}📄 {item}")
            with st.expander(f"预览 {item}"):
                preview_file(item_path)

# 文件预览
def preview_file(file_path):
    file_ext = os.path.splitext(file_path)[1].lower()
    
    try:
        if file_ext in [".txt", ".md", ".py", ".csv"]:  # 文本文件
            with open(file_path, "r", encoding="utf-8") as f:
                st.text(f.read())
        elif file_ext in [".jpg", ".jpeg", ".png", ".gif"]:  # 图片文件
            st.image(file_path)
        elif file_ext in [".mp4", ".avi", ".mov"]:  # 视频文件
            st.video(file_path)
        elif file_ext in [".mp3", ".wav"]:  # 音频文件
            st.audio(file_path)
        else:
            st.warning("不支持的文件类型预览")
    except Exception as e:
        st.error(f"无法预览文件:{str(e)}")

# 显示文件夹结构
if os.path.isdir(root_dir):
    display_folder_structure(root_dir)
else:
    st.error("文件夹路径无效,请重新输入。")

代码说明:

  1. 输入文件夹路径

    • 使用 st.text_input 让用户输入需要展示的根文件夹路径。
  2. 递归显示文件夹结构

    • display_folder_structure() 函数递归遍历指定文件夹,并通过缩进表示层级关系。
    • 对于每个文件,使用 st.expander 提供文件预览功能,点击展开后才显示文件内容。
  3. 文件预览功能

    • preview_file() 函数根据文件扩展名进行预览。
      • 文本文件(.txt.md.py.csv):直接读取并显示文件内容。
      • 图片文件(.jpg.png.gif):使用 st.image() 显示图片。
      • 视频文件(.mp4.avi.mov):使用 st.video() 显示视频。
      • 音频文件(.mp3.wav):使用 st.audio() 播放音频。
    • 如果文件格式不支持,会显示警告提示。
  4. 错误处理

    • 添加了对异常的捕获,防止读取或预览文件时出现问题,避免程序崩溃。

功能扩展:

  • 文件过滤:可以根据需要修改代码以过滤出特定类型的文件(如只显示文本文件或图片)。
  • 文件操作:可以扩展功能,添加文件下载、删除等操作。

为了优化大文件的预览体验,可以实现滚动加载,即用户滚动时逐步加载文件内容,而不是一次性读取整个文件。这种方式可以有效防止大文件占用过多内存和加载时间。

以下是一个优化后的代码,支持滚动加载文本文件的内容:

优化代码:

import os
import streamlit as st

# 设置页面标题
st.title("文件夹与文件展示和预览(支持滚动加载)")

# 获取文件夹路径
root_dir = st.text_input("请输入文件夹路径", value=".")

# 递归展示文件夹结构
def display_folder_structure(folder, level=0):
    for item in os.listdir(folder):
        item_path = os.path.join(folder, item)
        if os.path.isdir(item_path):
            # 显示文件夹名并递归显示其子文件夹
            st.markdown(f"{'  ' * level}📂 **{item}**")
            display_folder_structure(item_path, level + 1)
        else:
            # 显示文件名并添加文件预览按钮
            st.markdown(f"{'  ' * level}📄 {item}")
            with st.expander(f"预览 {item}"):
                preview_file(item_path)

# 文件预览(支持滚动加载)
def preview_file(file_path):
    file_ext = os.path.splitext(file_path)[1].lower()
    
    try:
        if file_ext in [".txt", ".md", ".py", ".csv"]:  # 文本文件滚动加载
            load_text_file_with_scroll(file_path)
        elif file_ext in [".jpg", ".jpeg", ".png", ".gif"]:  # 图片文件
            st.image(file_path)
        elif file_ext in [".mp4", ".avi", ".mov"]:  # 视频文件
            st.video(file_path)
        elif file_ext in [".mp3", ".wav"]:  # 音频文件
            st.audio(file_path)
        else:
            st.warning("不支持的文件类型预览")
    except Exception as e:
        st.error(f"无法预览文件:{str(e)}")

# 滚动加载文本文件
def load_text_file_with_scroll(file_path):
    """支持滚动加载的文本文件预览"""
    CHUNK_SIZE = 1000  # 每次加载的字符数
    with open(file_path, "r", encoding="utf-8") as f:
        # 初始化状态,保存已经加载的内容
        if 'file_offset' not in st.session_state:
            st.session_state.file_offset = 0
            st.session_state.file_chunk = ""

        # 读取当前文件块
        f.seek(st.session_state.file_offset)
        chunk = f.read(CHUNK_SIZE)
        st.session_state.file_chunk += chunk
        st.session_state.file_offset = f.tell()

        # 显示当前已加载的内容
        st.text(st.session_state.file_chunk)

        # 如果没有加载完全部文件,显示“加载更多”按钮
        if chunk:
            if st.button("加载更多"):
                load_text_file_with_scroll(file_path)
        else:
            st.info("文件已完全加载")

# 显示文件夹结构
if os.path.isdir(root_dir):
    display_folder_structure(root_dir)
else:
    st.error("文件夹路径无效,请重新输入。")

代码优化点:

  1. 滚动加载大文本文件

    • 使用 st.session_state 记录当前已经读取的文件偏移量(file_offset)和已读取的文本(file_chunk)。
    • 每次点击“加载更多”按钮时,继续从上次读取位置加载更多的文本(CHUNK_SIZE = 1000)。
    • 每次加载一部分内容,逐步显示,避免一次性加载整个文件。
  2. 状态保持

    • st.session_state 用于保持文件读取的进度,确保用户可以分段预览大文件。
  3. “加载更多”按钮

    • 当文件内容未完全加载时,显示“加载更多”按钮,用户点击后继续加载剩余部分。文件加载完毕时,显示“文件已完全加载”的提示。

工作流程:

  • 当用户点击预览文本文件时,文件会按 CHUNK_SIZE(如 1000 字符)逐块加载到页面中。
  • 页面每次只加载一小部分文本内容,用户可以通过点击“加载更多”按钮来逐步显示剩余部分,直到文件完全加载。

优势:

  • 减少内存占用:逐步读取文件内容,避免一次性加载大文件。
  • 提升用户体验:大文件可快速开始预览,用户可以自主选择是否继续加载。

可扩展性:

  • 支持更多文件类型:可以扩展 load_text_file_with_scroll() 函数,使其支持其他类型的文件(如 JSON 文件等)。
  • 更灵活的滚动控制:可以根据需要调整每次加载的块大小(CHUNK_SIZE),或添加滑动条控制。

http://www.kler.cn/a/318844.html

相关文章:

  • 使用CNN进行验证码识别:深度学习与图像预处理教程
  • 前端系统设计面试题(二)Javascript\Vue
  • 前端面试笔试(二)
  • Linux screen和cscope工具使用总结
  • C++ 并发专题 - 自旋锁的实现(Spinlock)
  • 编写红绿起爆线指标(附带源码下载)
  • 七层负载均衡和四层负载均衡的区别
  • 苍穹外卖学习笔记(十一)
  • 智谱AI:CogVideoX-2b——视频生成模型的得力工具
  • 短视频矩阵源码/短视频矩阵系统搭建/源码开发知识分享
  • Github + Hexo + Shoka搭建个人博客以及遇到的部分问题
  • mysqldump使用cmd窗口和powersell窗口导出sql中文乱码的问题
  • 工厂模式在短信发送中的应用 —— 以腾讯云、阿里云、华为云为例
  • Vue.js 中,@click 和 @click.stop的区别
  • Redis 多级缓存
  • 可以把台式电脑做成服务器吗
  • 状态模式原理剖析
  • OpenCV normalize() 函数详解及用法示例
  • 钰泰-ETA6964A 锂电池充电器IC
  • 基于STM32F103C8T6单片机的农业环境监测系统设计
  • 3D模型在UI设计中应用越来越多,给UI带来了什么?
  • API代理是什么?解读其原理与作用
  • golang context管理channel
  • 【数据库】sqlite
  • 【C++】托管类和托管函数
  • 大模型备案和互联网算法备案的区别?