python制作局域网内的FTP服务器

最近AI盛行,作为一个对python的初学者,经过几个小时的折腾,搞定了一个FTP小程序,用起来挺方便,适合手机和电脑传输文件,用起来方便、达到了预期效果。
1、效果图片



2、代码分享如下:

import socket
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import threading

class FTPServerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("FTP服务器")
        self.root.geometry("700x800")
        self.root.resizable(False, False)

        self.shared_folder = tk.StringVar()
        self.port = tk.IntVar(value=2121)
        self.username = tk.StringVar(value="user")
        self.password = tk.StringVar(value="12345")
        self.permission = tk.StringVar(value="读写")
        self.server = None
        self.server_thread = None
        self.progress_var = tk.DoubleVar(value=0)

        self.create_widgets()

    def create_widgets(self):
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 文件夹选择区域
        folder_frame = ttk.LabelFrame(main_frame, text="选择共享文件夹", padding="10")
        folder_frame.pack(fill=tk.X, pady=10)

        entry_folder = ttk.Entry(folder_frame, textvariable=self.shared_folder, state="readonly", font=("Arial", 10))
        entry_folder.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)

        btn_browse = ttk.Button(folder_frame, text="浏览", command=self.select_folder, width=10)
        btn_browse.pack(side=tk.RIGHT, padx=5)

        # 端口设置区域
        port_frame = ttk.LabelFrame(main_frame, text="服务器端口", padding="10")
        port_frame.pack(fill=tk.X, pady=10)

        entry_port = ttk.Entry(port_frame, textvariable=self.port, font=("Arial", 10))
        entry_port.pack(fill=tk.X, padx=5)

        # 用户名设置区域
        username_frame = ttk.LabelFrame(main_frame, text="用户名", padding="10")
        username_frame.pack(fill=tk.X, pady=10)

        entry_username = ttk.Entry(username_frame, textvariable=self.username, font=("Arial", 10))
        entry_username.pack(fill=tk.X, padx=5)

        # 密码设置区域
        password_frame = ttk.LabelFrame(main_frame, text="密码", padding="10")
        password_frame.pack(fill=tk.X, pady=10)

        entry_password = ttk.Entry(password_frame, textvariable=self.password, font=("Arial", 10))
        entry_password.pack(fill=tk.X, padx=5)

        # 权限设置区域
        permission_frame = ttk.LabelFrame(main_frame, text="共享文件夹权限", padding="10")
        permission_frame.pack(fill=tk.X, pady=10)

        permission_frame_inner = ttk.Frame(permission_frame)
        permission_frame_inner.pack(fill=tk.X)

        ttk.Radiobutton(permission_frame_inner, text="只读", variable=self.permission, value="只读", padding=5).pack(side=tk.LEFT, padx=10)
        ttk.Radiobutton(permission_frame_inner, text="读写", variable=self.permission, value="读写", padding=5).pack(side=tk.LEFT, padx=10)

        # 服务器状态区域
        status_frame = ttk.LabelFrame(main_frame, text="服务器状态", padding="10")
        status_frame.pack(fill=tk.X, pady=10)

        self.status_label = ttk.Label(status_frame, text="服务器未启动", font=("Arial", 10))
        self.status_label.pack(fill=tk.X)

        # IP地址显示
        ip_frame = ttk.LabelFrame(main_frame, text="局域网IP地址", padding="10")
        ip_frame.pack(fill=tk.X, pady=10)

        self.ip_label = ttk.Label(ip_frame, text="获取中...", font=("Arial", 10))
        self.ip_label.pack(fill=tk.X)

        # 文件传输进度区域
        progress_frame = ttk.LabelFrame(main_frame, text="文件传输进度", padding="10")
        progress_frame.pack(fill=tk.X, pady=10)

        self.progress_bar = ttk.Progressbar(progress_frame, variable=self.progress_var, maximum=100)
        self.progress_bar.pack(fill=tk.X)

        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=20)

        self.start_button = ttk.Button(button_frame, text="启动服务器", command=self.start_server, width=30)
        self.start_button.pack(side=tk.LEFT, padx=50, expand=True)

        self.stop_button = ttk.Button(button_frame, text="停止服务器", command=self.stop_server, width=30)
        self.stop_button.pack(side=tk.RIGHT, padx=50, expand=True)

        # 使用说明按钮
        readme_frame = ttk.Frame(main_frame)
        readme_frame.pack(fill=tk.X, pady=10)

        ttk.Button(readme_frame, text="使用说明", command=self.show_readme, width=20).pack(side=tk.BOTTOM, pady=10)

        # 初始化按钮状态
        self.update_button_states()

        # 获取本地IP
        self.update_local_ip()

    def select_folder(self):
        folder = filedialog.askdirectory()
        if folder:
            self.shared_folder.set(folder)

    def update_local_ip(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(("8.8.8.8", 80))
            local_ip = s.getsockname()[0]
            s.close()
            self.ip_label.config(text=f"本地IP: {local_ip}")
        except:
            self.ip_label.config(text="无法获取IP")

    def update_button_states(self):
        if self.server:
            self.start_button.config(state=tk.DISABLED)
            self.stop_button.config(state=tk.NORMAL)
        else:
            self.start_button.config(state=tk.NORMAL)
            self.stop_button.config(state=tk.DISABLED)

    def start_server(self):
        if not self.shared_folder.get():
            messagebox.showwarning("警告", "请选择共享文件夹")
            return

        if self.server:
            messagebox.showwarning("警告", "服务器已在运行")
            return

        port = self.port.get()
        if port < 1 or port > 65535:
            messagebox.showwarning("警告", "端口号必须在1-65535之间")
            return

        try:
            authorizer = DummyAuthorizer()

            # 根据权限设置不同的权限级别
            if self.permission.get() == "只读":
                perm = "elr"  # 只读权限
            else:
                perm = "elradfmw"  # 读写权限

            authorizer.add_user(self.username.get(), self.password.get(), self.shared_folder.get(), perm=perm)

            handler = FTPHandler
            handler.authorizer = authorizer

            self.server = FTPServer(("0.0.0.0", port), handler)
            self.server.max_cons = 256
            self.server.max_cons_per_ip = 5

            self.status_label.config(text=f"服务器已启动,端口: {port}")

            self.server_thread = threading.Thread(target=self.server.serve_forever)
            self.server_thread.daemon = True
            self.server_thread.start()

            self.update_button_states()

        except Exception as e:
            messagebox.showerror("错误", f"启动服务器失败: {str(e)}")
            self.server = None
            self.update_button_states()

    def stop_server(self):
        if self.server:
            try:
                self.server.close_all()
                self.server = None
                self.status_label.config(text="服务器已停止")
                self.update_button_states()
            except Exception as e:
                messagebox.showerror("错误", f"停止服务器失败: {str(e)}")
                self.update_button_states()

    def show_readme(self):
        readme_text = """
        本地FTP服务器使用说明

        1. 选择共享文件夹:
           - 点击“浏览”按钮,选择你想要共享的文件夹。

        2. 设置服务器端口:
           - 在“服务器端口”区域输入你想要使用的端口号(默认是2121)。

        3. 设置用户名和密码:
           - 在“用户名”和“密码”区域输入你想要设置的FTP服务器登录凭据。

        4. 设置共享文件夹权限:
           - 选择“只读”或“读写”权限。

        5. 启动服务器:
           - 点击“启动服务器”按钮启动FTP服务器。

        6. 连接FTP服务器:
           - 在手机上使用FTP客户端连接:
             - 地址:ftp://你的电脑局域网IP:端口号
             - 用户名:设置的用户名
             - 密码:设置的密码

        7. 停止服务器:
           - 点击“停止服务器”按钮停止FTP服务器。

        注意事项:
        - 确保电脑和手机在同一局域网下。
        - 如果无法连接,可能需要关闭防火墙或添加端口例外规则。
        """
        messagebox.showinfo("使用说明", readme_text)

if __name__ == "__main__":
    root = tk.Tk()
    app = FTPServerGUI(root)
    root.mainloop()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值