开发一个ftp上传客户端

news2024/11/20 11:47:17

文章目录

  • 需求
  • 分析
    • Tkinter
    • 基本用法
    • 多窗口切换
    • FTP上传
  • 程序打包
  • 源码

需求

项目中有个小功能模块 ,需要win下实现ftp上传功能,编写一个DEMO测试
要求

  • 界面简单
  • 选择本地文件 上传ftp服务器
  • 显示进度条
  • 显示状态
  • 上传完成后显示URL分享地址

分析

Tkinter

Tkinter 是 Python 的标准 GUI(图形用户界面)库,用于创建桌面应用程序。它是 Python 的官方 GUI 库,内置于Python 发行版中,因此无需额外安装即可使用。Tkinter 提供了一组用于创建窗口、对话框、按钮、文本框等 GUI
元素的类和方法。Tkinter 的外观和功能相对基础,复杂功能不使用

  • Tkinter 窗口(Tk):
    创建一个 Tkinter 应用程序时,首先需要创建一个顶层窗口。这通常是通过实例化
  • tkinter.Tk 类来实现的。
    Tkinter 小部件(Widgets):
    小部件是用户界面中用于交互的元素,如按钮、文本框、标签等。Tkinter 提供了多种小部件类,如 Button、Entry、Label 等。
  • 事件处理:
    Tkinter 通过事件处理机制来响应用户操作,如点击按钮、输入文本等。你可以通过绑定事件处理函数到小部件上,来处理这些事件。

基本用法

import tkinter as tk  
  
# 创建顶层窗口  
root = tk.Tk()  
root.title("Tkinter 示例")  
root.geometry("300x200")  # 设置窗口大小  
  
# 创建一个标签  
label = tk.Label(root, text="Hello, Tkinter!")  
label.pack(pady=20)  # 使用 pack 布局管理器,并设置上下填充  
  
# 定义一个按钮点击事件处理函数  
def on_button_click():  
    label.config(text="按钮已点击!")  
  
# 创建一个按钮,并绑定事件处理函数  
button = tk.Button(root, text="点击我", command=on_button_click)  
button.pack(pady=10)  
  
# 进入主事件循环  
root.mainloop()

在这里插入图片描述

多窗口切换

实现类似Tabs 组件以及选项卡功能

import tkinter as tk  
from tkinter import ttk  
  
class Tabs(tk.Frame):  
    def __init__(self, master=None, **kw):  
        super().__init__(master, **kw)  
        self.master = master  
        self.tabs = {}  # 用于存储选项卡和对应框架的字典  
        self.current_tab = None  # 当前显示的选项卡  
  
        # 创建一个框架来放置选项卡头部  
        self.header_frame = tk.Frame(self)  
        self.header_frame.pack(fill=tk.X)  
  
        # 创建一个框架来放置选项卡内容  
        self.content_frame = tk.Frame(self)  
        self.content_frame.pack(fill=tk.BOTH, expand=True)  
  
    def add_tab(self, tab_name, content):  
        # 创建选项卡头部按钮  
        tab_button = ttk.Button(self.header_frame, text=tab_name, command=lambda: self.switch_tab(tab_name))  
        tab_button.pack(side=tk.LEFT, fill=tk.X, expand=True)  
  
        # 创建内容框架并添加到字典中  
        content_frame = tk.Frame(self.content_frame)  
        content_frame.grid(row=0, column=0, sticky="nsew")  
        self.tabs[tab_name] = content_frame  
  
        # 将内容添加到内容框架中(这里假设content是一个widget或widget的创建函数)  
        if callable(content):  
            content(content_frame)  
  
        # 如果这是第一个选项卡,则默认显示它  
        if self.current_tab is None:  
            self.current_tab = tab_name  
            content_frame.grid_propagate(False)  # 禁止内容框架自动调整大小  
            content_frame.grid_rowconfigure(0, weight=1)  
            content_frame.grid_columnconfigure(0, weight=1)  
            self.content_frame.grid_rowconfigure(0, weight=1)  
            self.content_frame.grid_columnconfigure(0, weight=1)  
            content_frame.tkraise()  # 将内容框架置于顶层  
  
    def switch_tab(self, tab_name):  
        # 隐藏当前选项卡的内容框架  
        if self.current_tab:  
            self.tabs[self.current_tab].grid_remove()  
  
        # 显示新的选项卡内容框架  
        self.current_tab = tab_name  
        self.tabs[tab_name].grid(row=0, column=0, sticky="nsew")  
        self.tabs[tab_name].tkraise()  # 确保新的内容框架在顶层  
        self.tabs[tab_name].grid_propagate(False)  # 禁止内容框架自动调整大小(如果需要)  
  
# 示例使用  
def create_tab_content_a(frame):  
    label = tk.Label(frame, text="This is content for Tab A")  
    label.pack(pady=20, padx=20)  
  
def create_tab_content_b(frame):  
    entry = tk.Entry(frame)  
    entry.pack(pady=20, padx=20)  
  
root = tk.Tk()  
root.title("模拟实现TAB切换")  
root.geometry("600x400")  # 设置窗口大小 

tabs = Tabs(root)  
tabs.pack(fill=tk.BOTH, expand=True)  
  
# 添加选项卡  
tabs.add_tab("文件上传", create_tab_content_a)  
tabs.add_tab("文件列表", create_tab_content_b)  
  
root.mainloop()

在这里插入图片描述

FTP上传

在Python中实现FTP文件上传功能可以使用ftplib模块,这是一个内置的库,提供了对FTP协议的支持。首先,需要确保有权限访问目标FTP服务器。此外,需要准备好要上传的文件路径和FTP服务器的相关信息(如主机名、用户名、密码等)
可以先使用命令行工具进行测试确保没有问题

下面是 ftplib 中一些常用的函数和方法

  • FTP 类:
    构造函数: FTP(host=‘’, user=‘’, passwd=‘’, acct=‘’, timeout=None, source_address=None)
    创建一个 FTP 对象,并连接到指定的主机。
  • 登录相关的方法:
    login(user=‘’, passwd=‘’, acct=‘’): 使用提供的用户名、密码登录到 FTP 服务器。
    quit(): 发送 QUIT 命令给服务器并关闭连接。
  • 目录操作:
    cwd(pathname): 更改当前工作目录。
    pwd(): 获取当前工作目录。
    mkd(dirname): 创建新目录。
    rmd(dirname): 删除目录。
    nlst([arg]): 列出目录内容,如果提供了参数,则列出该目录下的内容;如果没有提供参数,则列出当前目录的内容。
    dir([arg]): 打印目录列表详情。
  • 文件传输:
retrbinary(cmd, callback, blocksize=8192, rest=None): 以二进制模式接收数据。
retrlines(cmd, callback=None): 以行文本模式接收数据。
storbinary(cmd, fp, blocksize=8192, callback=None, rest=None): 以二进制模式发送数据。
storlines(cmd, fp, callback=None): 以行文本模式发送数据。
  • 其他常用方法:
set_pasv(val=True): 设置是否使用被动模式(默认为 True)。
getwelcome(): 返回服务器欢迎信息。
rename(fromname, toname): 重命名远程文件或目录。
delete(filename): 删除远程文件。
size(filename): 返回远程文件大小。
voidcmd(cmd): 发送任意命令但不关心响应。

示例代码

from ftplib import FTP

# 连接到FTP服务器
ftp = FTP('your.ftp.server.com')
ftp.login('username', 'password')

# 切换到某个目录
ftp.cwd('/path/to/directory')

# 列出当前目录下的所有文件
files = ftp.nlst()
print("Files in directory:", files)

# 上传文件
with open('localfile.txt', 'rb') as file:
    ftp.storbinary('STOR remote_file.txt', file)
print("File has been uploaded.")

# 下载文件
with open('downloaded_file.txt', 'wb') as file:
    ftp.retrbinary('RETR remote_file.txt', file.write)
print("File has been downloaded.")

# 关闭连接
ftp.quit()

程序打包

需求 Windows 环境下将python程序打包为exe

在 Windows 下将 Python 程序打包成可执行文件(.exe),最常用的方法是使用 PyInstaller
安装
pip install pyinstaller

常见使用方法

pyinstaller --onefile my_script.py

–onefile 参数告诉 PyInstaller 将所有依赖和代码打包进一个单独的 .exe 文件中。
如果不加此参数,PyInstaller 会生成一个包含多个文件的目录。
默认情况下,生成的 .exe 文件位于 dist 目录下。你可以找到 dist/my_script.exe 文件。

–windowed:如果你的应用是一个 GUI 应用(如使用 Tkinter、PyQt 或 wxPython 编写的),并且你不希望显示控制台窗口,可以添加这个选项

–icon=your_icon.ico:为你的 .exe 文件指定一个图标

–hidden-import package_name:如果你的脚本动态导入了一些模块,而这些模块没有被自动检测到,你可以手动指定它们。

源码

import tkinter as tk  
from tkinter import ttk,filedialog
from ftplib import FTP  
from threading import Thread  
import os  
import time
import datetime
  
class FTPUploader:  
    def __init__(self, file_path, ftp_server, ftp_user, ftp_password, remote_path, progress_var,status_label):  
        self.file_path = file_path  
        self.ftp_server = ftp_server  
        self.ftp_user = ftp_user  
        self.ftp_password = ftp_password  
        self.remote_path = remote_path  
        self.progress_var = progress_var
        self.uploaded_bytes = 0  # Track the uploaded bytes
        self.status_label = status_label
  
    def upload(self):  
        try:  
            file_size = os.path.getsize(self.file_path)  
            with open(self.file_path, 'rb') as file:  
                ftp = FTP(self.ftp_server)  
                ftp.login(user=self.ftp_user, passwd=self.ftp_password)  
                  
                remote_dir, remote_filename = os.path.split(self.remote_path)  
                if remote_dir:  
                    ftp.cwd(remote_dir)  
                  
                # Define the callback function for progress updates  
                def update_progress(data): 
                    self.uploaded_bytes += len(data)  
                    # Calculate the progress percentage  
                    progress = self.uploaded_bytes / file_size * 100  
                    # Update the progress variable (which is linked to the progressbar)  
                    # Note: This may need to be done in a thread-safe way if the GUI is not thread-safe  
                    self.progress_var.set(progress)  
                  
                # Start the upload with the callback for progress updates  
                print(f"Uploading {self.file_path} to {self.remote_path}...")  
                ftp.storbinary(f'STOR {remote_filename}', file, callback=update_progress)  
                  
                ftp.quit()
                print(f"File {self.file_path} uploaded successfully to {self.remote_path}")
                self.status_label.config(text=f"上传{self.file_path}完成,\n播放地址为 http://10.31.32.40:8087/live/record/{remote_filename}")
                #self.status_label.config(text=f"上传{self.file_path}完成")
        except Exception as e:  
            print(f"Failed to upload file: {e}")
  
class UploadApp:  
    def __init__(self, root):
        self.timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        self.root = root
        # 创建选择文件按钮
        self.choose_button = tk.Button(root, text="选择文件", command=choose_file)
        self.choose_button.pack(pady=5)
        # 创建进度条
        self.progress_var = tk.DoubleVar()  
        self.progress_bar = ttk.Progressbar(root, orient="horizontal", maximum=100, mode="determinate", variable=self.progress_var)
        self.progress_bar.pack(fill=tk.X, padx=20, pady=10)
        #self.progress_bar.pack(pady=20)
        # 创建开始上传按钮
        self.start_button = tk.Button(root, text="开始上传", command=self.start_upload)  
        self.start_button.pack(pady=20)
        # 创建状态标签
        self.status_label = tk.Label(root, text="", fg="blue")  # 设置文本颜色为蓝色以便更明显
        self.status_label.pack(pady=10)
        # FTP credentials and file paths (these should be set by the user or securely stored)  
        #self.local_file_path = 'ftpclient.py'        
        self.ftp_server = '127.0.0.1'                
        self.ftp_user = 'ftpuser'                
        self.ftp_password = '123456'        

    def start_upload(self):
        if 'selected_file' not in globals() or not selected_file:
            self.status_label.config(text="请先选择一个文件!")
            return
        self.status_label.config(text="上传中...")
        self.progress_var.set(0)
        self.local_file_path = selected_file
        local_dir, local_filename = os.path.split(self.local_file_path)
        print(selected_file,self.local_file_path,local_dir,local_filename)
        self.remote_file_path = f'cctvlive/{local_filename}'
        #self.remote_file_path = f"cctvlive/{timestamp}.mp4"
        print("start_upload  ",self.remote_file_path)
        # Create an instance of the FTPUploader and run it in a separate thread  
        self.uploader = FTPUploader(self.local_file_path, self.ftp_server, self.ftp_user, self.ftp_password, self.remote_file_path, self.progress_var,self.status_label)  
        upload_thread = Thread(target=self.uploader.upload)  
        upload_thread.start()

def choose_file():
    # 打开文件选择对话框
    filename = filedialog.askopenfilename()
    if filename:
        file_label.config(text=f"选中的文件: {filename}")
        global selected_file
        selected_file = filename
        #progress_var.set(0)
        

selected_file=""

if __name__ == "__main__":  
	root = tk.Tk()
	root.title("直播录制文件上传")
	# 设置窗口大小
	root.geometry('400x250')

	# 创建并放置文件路径标签
	file_label = tk.Label(root, text="请选择要上传的文件...")
	file_label.pack(pady=10)



	app = UploadApp(root)  
	root.mainloop()

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199745.html

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

相关文章

【读书笔记·VLSI电路设计方法解密】问题6:超大规模集成电路(VLSI)设计实现的主要方法是什么

现代芯片设计实践的主要方法包括: 定制设计现场可编程门阵列 (FPGA)基于标准单元的设计 (ASIC)平台/结构化ASIC在定制设计方法中,每个晶体管都是手动设计和布局的。这种方法的主要优势在于电路可以高度优化以提高速度、减少面积或降低功耗。然而,由于涉及大量手工工作,这种…

什么是物联网nb水表?

物联网NB水表是一种利用NB-IoT(窄带物联网)技术实现远程数据传输的智能水表。这种水表不仅能够精确计量用户的用水量,还能通过无线通信技术实现数据的远程传输和管理。下面我们来详细介绍物联网NB水表的主要特点和功能。 一、基本概念 -定义:物联网NB水…

nVisual集成项目交付模式升级方案

集 成 项 目 的 普 遍 现 状 1 集成项目的普遍现状 设计、工程和运维各部门使用不同的软件工具,缺乏有效的协同,工程数据无法有效积累并转化为运维数据; 传统项目验收交付模式已经无法满足用户的需求,需要项目交付后协助用…

分治算法(6)_归并排序_交易逆序对的总数

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 分治算法(6)_归并排序_交易逆序对的总数 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论&#x1f48…

怎么去掉图片上的文字不留痕迹?学会这5种P图方法轻松解决

图片编辑已成为我们日常生活和工作中不可或缺的一部分。但有时候,图片上的一些文字却成了我们分享或使用的障碍。如何无痕去除图片上的文字呢?今天,我将为大家介绍5种高效工具,让你轻松P图,一起来学习下吧。 工具一&am…

ESP32利用WebServer进行设备配置

目标需求 利用esp32的WebServer功能&#xff0c;展示一个网页&#xff0c;对里面的参数进行配置&#xff0c;并以json文本格式保存到flash里面。 1、定义HTML const char index_html[] PROGMEM R"rawliteral( <!DOCTYPE html> <html lang"en"> …

前沿论文 M5Product 组会 PPT

对比学习&#xff08;Contrast learning&#xff09;&#xff1a;对比学习是一种自监督学习方法&#xff0c;用于在没有标签的情况下&#xff0c;通过让模型学习哪些数据点相似或不同来学习数据集的一般特征。假设一个试图理解世界的新生婴儿。在家里&#xff0c;假设有两只猫和…

PPT在线画SWOT分析图!这2个在线软件堪称办公必备!

swot分析ppt怎么做&#xff1f; swot分析是一个非常常用的战略分析框架&#xff0c;经常会在ppt中使用。想在ppt中绘制swot分析图&#xff0c;使用自带的形状工具可以制作出来&#xff0c;但绘制效率不够高&#xff0c;在需要大批量制作的场景下&#xff0c;会让人非常心累………

【WebGis开发 - Cesium】三维可视化项目教程---初始化场景

系列文章目录 【WebGis开发 - Cesium】三维可视化项目教程—视点管理 目录 系列文章目录引言一、Cesium引入项目1.1 下载资源1.2 项目引入Cesium 二、初始化地球2.1 创建基础文件2.1.1 创建Cesium工具方法文件2.1.2 创建主页面 2.2 看下效果 三、总结 引言 本教程主要是围绕Ce…

现场直击!2023望繁信科技产品发布会精彩回顾

2023望繁信科技产品发布会圆满结束。 感谢200余名企业代表、合作伙伴、媒体到场参会&#xff0c;感谢3万多位关注望繁信科技和流程挖掘的朋友在线观看直播。 在会上&#xff0c;我们正式分享了望繁信科技多年深耕流程挖掘领域的思考、积累和部署&#xff0c;发布了过去一年在…

Pyppeteer:如何在 Python 中使用 Puppeteer 和 Browserless?

Python 中的 Pyppeteer 是什么&#xff1f; Pyppeteer 是流行的 Node.js 库 Puppeteer 的 Python 移植版本&#xff0c;用于以编程方式控制无头 Chrome 或 Chromium 浏览器。 本质上&#xff0c;Pyppeteer 允许 Python 开发人员在 Web 浏览器中自动执行任务&#xff0c;例如抓…

webm格式怎么转换成mp4?值得给你推荐的几种简单方法

webm格式怎么转换成mp4&#xff1f;MP4支持多种音频和视频编解码器&#xff0c;如H.264和AAC&#xff0c;用户可以根据需要调整视频和音频质量&#xff0c;以满足不同需求。同时&#xff0c;许多视频编辑软件广泛支持MP4格式&#xff0c;使得剪辑、合成和特效处理变得更加便捷。…

人工智能、人机交互和机器人国际学术会议

第三届人工智能、人机交互和机器人国际学术会议 &#xff08;AIHCIR 2024&#xff09;组委会热忱地邀请您参与本届大会。本届大会旨在聚集领先的科学家、研究人员和学者&#xff0c;共同交流和分享在人工智能、人机交互和机器人各个方面的经验和研究成果&#xff0c;为研究人员…

【C++】模板(初识):函数模板、类模板

本篇主要介绍C中的模板初阶的一些知识。模板分为函数模板和类模板&#xff0c;我们一个一个来看。 1.函数模板 1.1函数模板概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实际的参数类型产生函数特定版本。…

LSTM时间序列模型实战——预测上证指数走势

LSTM时间序列模型实战——预测上证指数走势 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机器视觉&#xff0c;目标检测&#xff0c;图像分类&#xff0c;姿态识别&#xff0c;…

五款软件助你秒变职场达人

✨ 每天忙碌于工作&#xff0c;却感觉事半功倍&#xff1f;别担心&#xff0c;今天就为大家揭秘5款高效工作软件&#xff0c;让你秒变职场达人&#xff0c;效率直线飙升&#xff01;&#x1f389; 1️⃣ 亿可达 &#x1f3d7;️ 软件连接神器 &#x1f3af; 特点&#xff1a…

Java后端面试很水的,7天就能搞定!

随着Java的越来越卷&#xff0c;面试也直接上难度了&#xff0c;从以前的八股文到场景题了&#xff0c;尤其是有经验的去面试&#xff0c;场景题都是会问的&#xff0c;近期面试过的应该都深有体会&#xff01; 场景题230道&#xff1a; 1.分布式锁加锁失败后的等待逻辑是如何…

项目管理全流程包括哪些环节,一文读懂项目管理全流程

项目管理全流程是一个系统性、阶段性的过程&#xff0c;旨在确保项目从启动到完成的高效运行。该流程包括以下几个关键阶段&#xff1a;项目管理全流程是确保项目从启动到完成顺利进行的一系列阶段和活动的总称。 以下是基于项目管理全流程对项目管理的描述&#xff1a; 一、…

单路测径仪的详细介绍

蓝鹏测控单路测径仪是一种高精度、高效率的在线检测设备&#xff0c;广泛应用于线缆、电缆、电线、胶管、塑料管、金属丝等行业的生产过程中。以下是对该产品的详细介绍&#xff1a; 一、核心技术与工作原理 蓝鹏测控单路测径仪以光电检测为核心&#xff0c;结合单片机、LED灯、…

Qt-QStatusBar窗口状态栏相关操作(48)

目录 描述 使用 设置临时消息 添加子控件 添加 Labe 添加 进度条 从右边添加 按钮 描述 状态栏是应⽤程序中输出简要信息的区域。⼀般位于主窗⼝的最底部&#xff0c;⼀个窗⼝中最多只能有⼀个状态栏。在 Qt 中&#xff0c;状态栏是通过 QStatusBar类 来实现的。在状态…