streamlit 文件上传保存+预览

news2024/9/25 11:09:42

以下是一个使用 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.coloradmin.cn/o/2163385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程,端口号,网络字节序,udp

前面一篇我们讲了网络的基础&#xff0c;网络协议栈是什么样的&#xff0c;数据如何流动传输的&#xff1b;接下来这篇&#xff0c;我们将进行实践操作&#xff0c;真正的让数据跨网络进行传输&#xff1b; 1.网络编程储备知识 1.1 初步认识网络编程 首先我们需要知道我们的…

Facebook对现代社交互动的影响

自2004年成立以来&#xff0c;Facebook已经成为全球最大的社交媒体平台之一&#xff0c;改变了人们的交流方式和社交互动模式。作为一个数字平台&#xff0c;Facebook不仅为用户提供了分享生活点滴的空间&#xff0c;也深刻影响了现代社交互动的各个方面。本文将探讨Facebook如…

Ollama在Windows安装,使用,简单调用API

一、安装ollama 1、安装 在Windows本地安装ollama&#xff0c;官方网页&#xff1a;https://ollama.com/download/windows 下载完安装包&#xff0c;安装就好&#xff0c;默认应该是C盘。应该是没办法改&#xff0c;如果有小伙伴能改&#xff0c;也请告知一下。 2、验证安装…

华为OD机试 - 数据单元的变量替换 - 分治、递归(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

基于yolov8+deepsort+gradio实现目标追踪演示

【效果展示】 【测试环境】 ultralytics8.2.95 gradio4.26.0 torch1.9.0cu111 理论上支持最新ultralytics版本 【实现部分代码】 with gr.Blocks() as demo:with gr.Tab("追踪"):# 使用Markdown显示文本信息&#xff0c;介绍界面的功能gr.Markdown(""…

linux固定串口别名

最近项目功能要求&#xff0c;需要将插入设备的串口设备占用的端口号固定住&#xff0c;这里记录一下设置过程方便以后查阅。 linux固定串口别名 配置过程相关补充 配置过程 列出当前插入USB端口的设备&#xff1a; lsusb查看当前设备的端口号&#xff1a; ls dev/查看当前设…

无人机飞手培训及巡检、吊运等飞行服务一体化技术详解

在无人机行业日益兴起的背景下&#xff0c;培养专业、合格的无人机飞手成为首要任务。飞手培训基础涵盖理论学习与安全意识建立两大方面。理论学习包括无人机基础知识&#xff08;如无人机类型、结构、原理&#xff09;、航空法规&#xff08;如民用无人驾驶航空器实名制登记管…

旧衣回收小程序搭建,开发功能优势

随着人们生活水平、消费水平的提高&#xff0c;在日常生活中产生了大量的限制物品&#xff0c;为了减少浪费&#xff0c;越来越多的人开始重视环保回收。旧衣物作为一种新型的回收方式&#xff0c;也逐渐得到了大众的关注&#xff0c;旧衣物回收市场发展规模也在持续上升&#…

Certbot自动申请并续期https证书

Certbot自动申请并续期https证书 一、 安装 Certbot&#xff1a;使用命令安装 Certbot&#xff1a; dnf install certbot python3-certbot-nginx获取 SSL 证书&#xff1a;运行 Certbot 命令来获取并安装 SSL 证书。 示例命令&#xff0c;替换其中的域名和路径信息&#xff1a…

PHP API 框架:构建高效API的利器【电商API接口】

在当今快速发展的互联网时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为连接不同应用程序和服务的关键。PHP&#xff0c;作为一种流行的服务器端脚本语言&#xff0c;提供了多种强大的框架来简化API的开发。本文将介绍PHP API框架的重要性&#xff0c;以及…

java并发编程笔记 之 线程和进程

文章目录 前言线程线程优先级和时间片创建多线程及运行线程的状态 进程查看进程的命令进程的通信方式 线程和进程的区别从关系上疑问集锦 前言 并发 1、并发是指在同一时间段内&#xff0c;计算机系统能够处理多个任务的能力。 2、在并发编程中&#xff0c;我们可以理解为多个…

chapter17-多线程基础——(自定义泛型)——day20

580-程序进程线程 581-并发并行 并发和并行也可以同时进行 582-继承Thread创建线程 583-多线程机制 主线程和子线程交替执行 单核&#xff1a;两个线程并发 多核&#xff1a;两个线程并行 主线程结束&#xff0c;不是说进程就结束&#xff0c;进程要等所有线程结束 584-为什…

模型Alignment之RLHF与DPO

1. RLHF (Reinforcement Learning from Human Feedback) RLHF 是一种通过人类反馈来强化学习的训练方法&#xff0c;它能够让语言模型更好地理解和执行人类指令。 RLHF 的三个阶段 RLHF 的训练过程一般分为三个阶段&#xff1a; 监督微调&#xff08;Supervised Fine-Tuning,…

认知杂谈82《跳出信息茧房,持续精进》

内容摘要&#xff1a; 互联网时代&#xff0c;信息丰富&#xff0c;但便捷性削弱了我们的好奇心。互联网是双刃剑&#xff0c;快速获取知识的同时&#xff0c;也让我们陷入“信息茧房”&#xff0c;限制视野。 好奇心减少&#xff0c;部分原因是互联网的“懒惰效应”&#xff0…

国家标准和团体标准有什么区别?

国家标准和团体标准的区别主要体现在以下几个方面&#xff1a; 1. 制定标准的主体不同&#xff1a;国家标准是由国家机构通过并公开发布的标准&#xff1b;团体标准是由学会、协会、商会、联合会、产业技术联盟等社会团体协调相关市场主体共同制…

【项目实战】如何在项目中基于 Spring Boot Starter 开发简单的 SDK

什么是SDK 通常在分布式项目中&#xff0c;类和方法是不能跨模块使用的。为了方便开发者的调用&#xff0c;我们需要开发一个简单易用的SDK&#xff0c;使开发者只需关注调用哪些接口、传递哪些参数&#xff0c;就像调用自己编写的代码一样简单。实际上&#xff0c;RPC(远程过…

element下拉框联动 或 多选 回显数据后页面操作不生效问题解决

第一种:多选回显不生效 解决方式: 代码: <el-form-item label"系统" prop"Key"> <el-select v-model"addForm.Key" multiple placeholder"请选择" change"$forceUpdate()"> <el-option v-for"item …

Typescript高级用法

TypeScript 是一种类型安全的 JavaScript 超集&#xff0c;除了基本类型和对象类型之外&#xff0c;TypeScript 还提供了一些高级类型系统&#xff0c;使得我们可以更好地处理复杂的数据结构和业务逻辑。本文将深入探讨 TypeScript 的高级类型系统&#xff0c;以更好地理解和使…

【AI大模型应用开发】【综合实战】AI+搜索,手把手带你实现属于你的AI搜索引擎(附完整代码)

现在市面上有很多的AI搜索的应用或插件&#xff0c;一直想学习其背后的实现原理。今天咱们就学习一下&#xff0c;并且亲自动手实践&#xff0c;从0开始&#xff0c;搭建一个自己的AI搜索引擎。最终实现效果如下&#xff1a; 话不多说&#xff0c;开干。 本文代码参考&#xff…

累加求和-C语言

1.问题&#xff1a; 计算123……100的和&#xff0c;要求分别用while、do while、for循环实现。 2.解答&#xff1a; 累加问题&#xff0c;先后将100个数相加。要重复进行100次加法运算&#xff0c;可以用循环结构来实现。重复执行循环体100次&#xff0c;每次加一个数。 3.代…