找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 14|回复: 0

用AI开发软件:FTP管理工具(附完整代码)

[复制链接]

3

主题

1

回帖

21

积分

新手上路

积分
21
发表于 2025-3-29 11:06:05 | 显示全部楼层 |阅读模式
在当今快速发展的技术世界中,人工智能(AI)正在改变我们开发软件的方式。无论是代码生成、问题调试,还是架构设计,AI工具都能为开发者提供强大的支持。今天,我们将探索如何利用AI开发一个简单的FTP(文件传输协议)工具,并附上完整的代码实现。
技术栈
  • 编程语言:Python
  • AI工具:DeepSeek(用于代码生成和问题排查)
  • 核心库:
    1. from pyftpdlib.authorizers import DummyAuthorizer
    2. from pyftpdlib.handlers import FTPHandler
    3. from pyftpdlib.servers import FTPServer
    复制代码
    当前功能
    • 多IP地址自动检测
    • 实时连接数统计
    • 细粒度权限控制
    • 操作日志记录
    软件截图

  • 完整代码(单文件)
    代码完全根据个人习惯和喜好进行编写;大家可以根据代码中包含的各项注释进行阅读或修改。
    1. import tkinter as tk
    2. from tkinter import ttk, filedialog, messagebox, scrolledtext
    3. from pyftpdlib.authorizers import DummyAuthorizer
    4. from pyftpdlib.handlers import FTPHandler
    5. from pyftpdlib.servers import FTPServer
    6. import threading
    7. import socket
    8. import webbrowser
    9. from typing import List

    10. class FTPServerGUI:
    11.     def __init__(self, root):
    12.         self.root = root
    13.         self.server = None
    14.         self.connection_count = 0
    15.         self.setup_ui()
    16.         self.show_filtered_ips()
    17.         self.display_welcome_msg()

    18.     def setup_ui(self):
    19.         # 主窗口设置
    20.         self.root.title("FTP服务器 v1.0")
    21.         self.root.geometry("560x500")
    22.         self.root.minsize(560, 480)

    23.         # 配置网格布局权重
    24.         self.root.columnconfigure(0, weight=1)
    25.         self.root.columnconfigure(1, weight=1)
    26.         self.root.rowconfigure(4, weight=1)  # 日志区域行

    27.         # 顶部信息栏
    28.         top_info = ttk.Frame(self.root)
    29.         top_info.grid(row=0, column=0, columnspan=2, padx=10, pady=5, sticky="ew")

    30.         # 当前连接数显示
    31.         self.conn_label = ttk.Label(top_info, text="当前连接: 0", foreground="green")
    32.         self.conn_label.pack(side="right", padx=10)

    33.         # IP地址显示
    34.         ttk.Label(top_info, text="服务器IP:").pack(side="left")
    35.         self.ip_label = ttk.Label(top_info, text="正在获取...", foreground="blue")
    36.         self.ip_label.pack(side="left", padx=5)

    37.         # 配置框架
    38.         config_frame = ttk.LabelFrame(self.root, text="服务器配置")
    39.         config_frame.grid(row=1, column=0, columnspan=2, padx=10, pady=5, sticky="ew")

    40.         # 输入字段布局
    41.         input_grid = ttk.Frame(config_frame)
    42.         input_grid.pack(fill="x", padx=5, pady=5)

    43.         # 端口配置
    44.         ttk.Label(input_grid, text="端口:").grid(row=0, column=0, padx=5, sticky="w")
    45.         self.port_entry = ttk.Entry(input_grid, width=8)
    46.         self.port_entry.grid(row=0, column=1, sticky="w")
    47.         self.port_entry.insert(0, "21")

    48.         # 用户配置
    49.         ttk.Label(input_grid, text="用户:").grid(row=0, column=2, padx=(15,5), sticky="w")
    50.         self.user_entry = ttk.Entry(input_grid, width=12)
    51.         self.user_entry.grid(row=0, column=3, sticky="w")
    52.         self.user_entry.insert(0, "user")

    53.         # 密码配置
    54.         ttk.Label(input_grid, text="密码:").grid(row=0, column=4, padx=(15,5), sticky="w")
    55.         self.pass_entry = ttk.Entry(input_grid, width=12, show="*")
    56.         self.pass_entry.grid(row=0, column=5, sticky="w")
    57.         self.pass_entry.insert(0, "123")

    58.         # 目录选择
    59.         dir_frame = ttk.Frame(config_frame)
    60.         dir_frame.pack(fill="x", padx=5, pady=5)
    61.         ttk.Button(dir_frame, text="选择FTP目录", command=self.select_directory).pack(side="left")
    62.         self.dir_label = ttk.Label(dir_frame, text="未选择目录", foreground="gray")
    63.         self.dir_label.pack(side="left", padx=10)

    64.         # 权限设置框架
    65.         perm_frame = ttk.LabelFrame(self.root, text="用户权限设置")
    66.         perm_frame.grid(row=2, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")

    67.         # 三列布局
    68.         self.perm_vars = {
    69.             'e': tk.BooleanVar(value=True),
    70.             'l': tk.BooleanVar(value=True),
    71.             'r': tk.BooleanVar(value=True),
    72.             'a': tk.BooleanVar(),
    73.             'd': tk.BooleanVar(),
    74.             'f': tk.BooleanVar(),
    75.             'm': tk.BooleanVar(value=True),
    76.             'M': tk.BooleanVar(),
    77.             'w': tk.BooleanVar(value=True),
    78.         }

    79.         cols = [ttk.Frame(perm_frame) for _ in range(3)]
    80.         for i, col in enumerate(cols):
    81.             col.grid(row=0, column=i, sticky="nsew", padx=5)
    82.             perm_frame.columnconfigure(i, weight=1)

    83.         # 权限项分布
    84.         permissions = [
    85.         ("上传文件 (w)", 'w', 0),
    86.         ("下载文件 (r)", 'r', 0),
    87.         ("删除文件 (d)", 'd', 0),
    88.         ("查看列表 (l)", 'l', 1),
    89.         ("切换目录 (e)", 'e', 1),
    90.         ("创建目录 (m)", 'm', 1),
    91.         ("修改权限 (M)", 'M', 2),
    92.         ("重命名 (f)", 'f', 2),
    93.             ("追加文件 (a)", 'a', 2)
    94.         ]

    95.         for text, key, col_idx in permissions:
    96.             ttk.Checkbutton(cols[col_idx], text=text, variable=self.perm_vars[key]).pack(anchor="w", pady=2)

    97.         # 控制按钮
    98.         btn_frame = ttk.Frame(self.root)
    99.         btn_frame.grid(row=3, column=0, columnspan=2, pady=10)
    100.         self.start_btn = ttk.Button(btn_frame, text="启动服务器", command=self.toggle_server)
    101.         self.start_btn.pack(side="left", padx=5)

    102.         # 日志区域
    103.         log_frame = ttk.LabelFrame(self.root, text="服务器日志")
    104.         log_frame.grid(row=4, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
    105.         self.log_text = scrolledtext.ScrolledText(log_frame, wrap=tk.WORD, height=8)
    106.         self.log_text.pack(expand=True, fill="both")

    107.         # 博客链接
    108.         blog_link = ttk.Label(self.root, text="zneVue & AI", foreground="blue", cursor="hand2")
    109.         blog_link.grid(row=5, column=1, padx=10, pady=5, sticky="se")
    110.         blog_link.bind("<Button-1>", lambda e: webbrowser.open("https://www.52pojie.cn/home.php?mod=space&uid=2299786"))

    111.         # 布局权重配置
    112.         perm_frame.rowconfigure(0, weight=1)
    113.         log_frame.rowconfigure(0, weight=1)
    114.         log_frame.columnconfigure(0, weight=1)

    115.     def show_filtered_ips(self) -> List[str]:
    116.         try:
    117.             ips = socket.gethostbyname_ex(socket.gethostname())[2]
    118.             filtered_ips = [
    119.                 ip for ip in ips
    120.                 if ip != "127.0.0.1"
    121.                 and not ip.startswith("169.254.")
    122.             ]

    123.             self.ip_label.config(text=", ".join(filtered_ips) if filtered_ips else "未找到有效IP")
    124.             return filtered_ips
    125.         except Exception as e:
    126.             self.ip_label.config(text=f"获取IP失败: {str(e)}")
    127.             return []

    128.     def is_valid_ip(self, ip: str) -> bool:
    129.         if ip.startswith("127.") or ip == "::1":
    130.             return False
    131.         if ip.startswith("169.254."):  # APIPA地址
    132.             return False
    133.         if ip.startswith("172.17."):  # Docker默认地址
    134.             return False
    135.         if ip.startswith("192.168.") or ip.startswith("10."):  # 内网地址
    136.             return True  # 保留显示内网地址
    137.         return True

    138.     def select_directory(self):
    139.         directory = filedialog.askdirectory()
    140.         if directory:
    141.             self.dir_label.config(text=directory, foreground="black")

    142.     def update_connection_count(self, delta: int):
    143.         """线程安全更新连接数"""
    144.         self.connection_count += delta
    145.         self.root.after(0, self.conn_label.config,
    146.                       {"text": f"当前连接: {self.connection_count}"})

    147.     def log_message(self, msg: str):
    148.         self.log_text.insert(tk.END, msg + "\n")
    149.         self.log_text.see(tk.END)

    150.     def thread_safe_log(self, msg: str):
    151.         self.root.after(0, self.log_message, msg)

    152.     def toggle_server(self):
    153.         if self.server is None:
    154.             self.start_server()
    155.         else:
    156.             self.stop_server()

    157.     def start_server(self):
    158.         port = int(self.port_entry.get())
    159.         user = self.user_entry.get()
    160.         password = self.pass_entry.get()
    161.         directory = self.dir_label.cget("text")

    162.         if not all([user, password, directory]) or directory == "未选择目录":
    163.             messagebox.showerror("错误", "请填写所有必填字段!")
    164.             return

    165.         perm = ''.join([k for k, v in self.perm_vars.items() if v.get()])
    166.         if not perm:
    167.             messagebox.showerror("错误", "请至少选择一个权限!")
    168.             return

    169.         class CustomHandler(FTPHandler):
    170.             gui = self  # 引用GUI实例

    171.             def on_connect(self):
    172.                 self.gui.update_connection_count(1)
    173.                 self.gui.thread_safe_log(f"[连接] {self.remote_ip}:{self.remote_port} 已连接")

    174.             def on_disconnect(self):
    175.                 self.gui.update_connection_count(-1)
    176.                 self.gui.thread_safe_log(f"[连接] {self.remote_ip}:{self.remote_port} 断开连接")

    177.             def on_login(self, username):
    178.                 self.gui.thread_safe_log(f"[认证] 用户 {username} 登录成功")

    179.             def on_login_failed(self, username, password):
    180.                 self.gui.thread_safe_log(f"[认证] 登录失败 用户名: {username}")

    181.         try:
    182.             authorizer = DummyAuthorizer()
    183.             authorizer.add_user(user, password, directory, perm=perm)

    184.             handler = CustomHandler
    185.             handler.authorizer = authorizer

    186.             self.server = FTPServer(("0.0.0.0", port), handler)
    187.             self.thread_safe_log(f"[状态] 服务已启动于 0.0.0.0:{port}")
    188.             self.thread_safe_log(f"[提示] 可用地址: {self.ip_label.cget('text')}")
    189.             self.start_btn.config(text="停止服务器")

    190.             server_thread = threading.Thread(target=self.server.serve_forever)
    191.             server_thread.daemon = True
    192.             server_thread.start()
    193.         except Exception as e:
    194.             self.thread_safe_log(f"[错误] 启动失败: {str(e)}")

    195.     def stop_server(self):
    196.         if self.server:
    197.             self.server.close_all()
    198.             self.server = None
    199.             self.connection_count = 0
    200.             self.conn_label.config(text="当前连接: 0")
    201.             self.thread_safe_log("[状态] 服务器已停止")
    202.             self.start_btn.config(text="启动服务器")

    203.     def display_welcome_msg(self):
    204.         """显示欢迎信息"""
    205.         welcome_text = """=== FTP服务器 v1.0 ===
    206. 【使用指南】
    207. 1. 选择FTP目录 -> 设置用户权限 -> 启动服务
    208. 2. 客户端连接地址显示在顶部IP栏
    209. 3. 日志区域实时显示连接状态
    210. 【常用命令帮助】
    211. USER [用户名]   - 登录认证
    212. PASS [密码]     - 输入密码
    213. LIST            - 列出文件列表
    214. RETR [文件名]   - 下载文件
    215. STOR [文件名]   - 上传文件
    216. QUIT/EXIT       - 断开连接
    217. 当前版本功能:
    218. • 多IP地址自动检测
    219. • 实时连接数统计
    220. • 细粒度权限控制
    221. • 操作日志记录
    222. """
    223.         self.log_text.configure(state='normal')
    224.         self.log_text.delete(1.0, tk.END)
    225.         self.log_text.insert(tk.END, welcome_text)

    226.         # 设置文本样式
    227.         self.log_text.tag_configure("title", foreground="#2E75B6", font=('微软雅黑', 10, 'bold'))
    228.         self.log_text.tag_add("title", "1.0", "1.19")

    229. if __name__ == "__main__":
    230.     root = tk.Tk()
    231.     app = FTPServerGUI(root)
    232.     root.mainloop()
    复制代码
    想使用但是本地没有python的朋友可以直接食用。
    (代码经过 pystaller 本地打包,没有任何病毒,请放心使用)

  • https://zheyue.lanzoue.com/iogdb2rsuppi

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|一起港湾 ( 青ICP备2025004122号-1 )

GMT+8, 2025-4-8 04:04 , Processed in 0.087538 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表