使用python实现可视化ftp客户端(本地文件展示和搜索功能、ftp文件展示和搜索功能以及上传和下载功能)

python实现可视化ftp客户端

  • 效果展示
  • 使用说明
  • bug说明
  • 源码展示

效果展示

使用python实现可视化ftp客户端(本地文件展示和搜索功能、ftp文件展示和搜索功能以及上传和下载功能)_第1张图片

使用说明

1.先选择本地的一个目录进行文件展示
2.本地搜索是基于第一步选择本地目录的路径进行搜索的
3.ftp搜索是基于当前ftp显示这个页面进行搜索的
4.左边本地展示框和右边ftp展示框支持拖拽上传,前提是先要选择一个目录。

bug说明

在这个项目中有两个最大的bug还未解决
1.上传到ftp中文目录中会出现乱码
2.上传和下载显示的进度条是一个假的进度条
欢迎各位大佬对这两个bug进行修改

源码展示

import tkinter as tk
from tkinter import ttk
from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_center import BottomMenuBarCenter
from ftp_client_alter_bug.seek.win_search import WinSearch
from ftp_client_alter_bug.top_menu.top_menu_bar import TopMenuBar
from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_left import BottomMenuBarleft
from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_right import BottomMenuBarRight
from ftp_client_alter_bug.tree.win_tree import WinTree
from ftp_client_alter_bug.tree.ftp_tree import FtpTree
from ftp_client_alter_bug.win_ftp_drag.ftpdrag import FtpDrag
from ftp_client_alter_bug.win_ftp_drag.windrag import WinDrag

win = tk.Tk()
win.title("FTP客户端")
win.geometry("1200x700")
win.resizable(0, 0)


xuanzhe_win_path = []
win_path = []
ftp_path = []
win_search_name = []
win_search_path = []
ftp_search_path = []
ftp_list = []
ftp_tree_list = []
win_xuanze_tree = []
win_search_tree = []
path = "初始化占位"

top_frame = tk.Frame(win, width="1200", height="60")
top_frame.place(x=0, y=5)
top_menu = TopMenuBar(top_frame, path, win, win_search_path, ftp_list, xuanzhe_win_path)
top_menu.logo()

top_menu.open_wenjian()
# top_menu.search_box()
top_menu.name_ip("", "")
top_menu.exit_login(ftp_tree_list, ftp_path, ftp_list)
top_menu.login_in(ftp_path, ftp_list, ftp_tree_list)
top_menu.lishi_login_in(ftp_path, ftp_list, ftp_tree_list)


left_frame = tk.Frame(win, width="350", height="540")
left_frame.place(x=10, y=90)
tree = ttk.Treeview(left_frame, show="tree", height=26)
tree.column("#0", width=350)
st = ttk.Style()
st.configure("Treeview", font=("宋体", 13))
winftpdrag = WinDrag(left_frame, win_path, xuanzhe_win_path, tree)
winftpdrag.execute()

win_xuanze_tree.clear()
win_xuanze_tree.append(tree)

wintree = WinTree(path, win_path, tree)

top_menu.local_mulu(win_path, tree)



# 创建两个一模一样的frame实现一个注销一个加载
win_center_frame = tk.Frame(win, width="420",bg="green", height="540")
win_center_frame.place(x=350, y=90)
search_path = r"D:\\python_daima"
search_name = "9999"

win_tree = ttk.Treeview(win_center_frame, show="tree", height=26)

win_tree.column("#0", width=440)
st = ttk.Style()
st.configure("Treeview", font=("宋体", 12))
win_search_tree.clear()
win_search_tree.append(win_tree)

winsearch = WinSearch(path, search_name, win_search_path, win_tree)

top_menu.search_box(win_search_name, win_search_tree, ftp_search_path, ftp_list)



right_frame = tk.Frame(win, width="420", height="540")
right_frame.place(x=790, y=90)

tree_ftp = ttk.Treeview(right_frame, show="tree", height=26, columns=("shijian", "wenjiantype"))
tree_ftp.column("#0", width=250)
tree_ftp.column("shijian", width=80)
tree_ftp.column("wenjiantype", width=60)

ftp_tree_list.append(tree_ftp)

st = ttk.Style()
st.configure("Treeview", font=("宋体", 13))


bommot_frame_left = tk.Frame(win, width="350", height="60")
bommot_frame_left.place(x=0, y=635)
bommot_menu_left = BottomMenuBarleft(bommot_frame_left)
bommot_menu_left.win_chuangjian_mulu(win_path, xuanzhe_win_path, tree)
bommot_menu_left.win_chuangjian_wenjian(win_path, xuanzhe_win_path, tree)
bommot_menu_left.win_delete_mulu(win_path, xuanzhe_win_path, tree)
bommot_menu_left.win_delete_wenjian(win_path, xuanzhe_win_path, tree)

# bommot_menu_left.shangchaung(win, ftp_path, ftp_list, ftp_frame, ftp_tree, win_path, bommot_frame_center)
bommot_menu_left.open_wenjian(win_path)
bommot_menu_left.gexian()


bommot_frame_center = tk.Frame(win,  width="500", height="60")
bommot_frame_center.place(x=350, y=635)
bottom_menu_center = BottomMenuBarCenter(bommot_frame_center)
bottom_menu_center.delete_mulu(win_search_path, xuanzhe_win_path, win_search_name, win_tree, win_path, tree)
bottom_menu_center.open_weizhi(win_search_path)
bottom_menu_center.delete_wenjian(ftp_list, tree_ftp, ftp_path, win_search_name, win_search_tree, ftp_search_path)
bottom_menu_center.xiazai_wenjian(ftp_list, win_path, xuanzhe_win_path, bommot_frame_center, tree, ftp_search_path)
bottom_menu_center.gexian()

ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
ftpdrag = FtpDrag(right_frame, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp)
ftpdrag.execute()


bommot_menu_left.shangchaung(ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp)

bommot_frame_right = tk.Frame(win, width="350", height="60")
bommot_frame_right.place(x=850, y=635)
bommot_menu_right = BottomMenuBarRight(bommot_frame_right)
bommot_menu_right.geban()
bommot_menu_right.ftp_chaungjian_mulu(ftp_path, ftp_list, tree_ftp)
bommot_menu_right.ftp_jinru_xj(ftp_path, ftp_list, tree_ftp)
bommot_menu_right.ftp_delete_mulu(ftp_path, ftp_list, tree_ftp)
bommot_menu_right.ftp_delete_wenjian(ftp_path, ftp_list, tree_ftp)
bommot_menu_right.xiazai(ftp_list, ftp_path, win_path, xuanzhe_win_path, bommot_frame_center, tree)
bommot_menu_right.ftp_fh_sj(ftp_path, ftp_list, tree_ftp)


tk.mainloop()
import tkinter as tk
import os
from tkinter.messagebox import showinfo

from ftp_client_alter_bug.tree.ftp_tree import FtpTree
from ftp_client_alter_bug.tree.win_tree import WinTree
from ftp_client_alter_bug.seek.ftp_search import FtpSearch
from ftp_client_alter_bug.seek.win_search import WinSearch


class BottomMenuBarCenter:
    def __init__(self, bommot_frame_center):
        self.bommot_frame_center = bommot_frame_center

    # win删除文件
    def delete_mulu(self, win_search_path, xuanzhe_win_path, win_search_name, win_tree, win_path, tree):
        def delete_mulu_button():
            try:
                # 也可以递归删除文件
                def delAll(path):
                    if os.path.isdir(path):
                        files = os.listdir(path)
                        # 遍历并删除文件
                        for file in files:
                            p = os.path.join(path, file)
                            if os.path.isdir(p):
                                # 递归
                                delAll(p)
                            else:
                                os.remove(p)
                        # 删除文件夹
                        os.rmdir(path)
                    else:
                        os.remove(path)

                delAll(win_search_path[0])

                table = win_tree
                items = table.get_children()
                [table.delete(item) for item in items]

                win_name = win_search_name[0]
                winsearch = WinSearch(xuanzhe_win_path[0], win_name, win_search_path, win_tree)
                winsearch.search()

                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]

                wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()
            except:
                showinfo("错误提示", "路径选择异常!")


        delete_mulu_but = tk.Button(self.bommot_frame_center, text="删除文件", command=delete_mulu_button, font=("宋体", 13), relief="flat")
        delete_mulu_but.place(x=15, y=2)

    # 打开window上文件所在的位置
    def open_weizhi(self, win_search_path):
        def open_weizhi_button():
            try:
                os.startfile(rf"{win_search_path[0]}")
            except:
                showinfo("错误提示", "未选择路径!")
        open_weizhi_but = tk.Button(self.bommot_frame_center, text="打开文件", command=open_weizhi_button, font=("宋体", 13), relief="flat")
        open_weizhi_but.place(x=15, y=35)

    # ftp删除文件
    def delete_wenjian(self, ftp_list, tree_ftp, ftp_path, win_search_name, win_search_tree, ftp_search_path):
        def delete_wenjian_button():
            try:
                ftp_list[0].delete(ftp_search_path[0])

                if str(ftp_list[0].pwd()) != "/":
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_list[0].pwd())
                else:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("/")

                win_name = win_search_name[0]
                table = win_search_tree[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                ftpsearch = FtpSearch(ftp_list[0], win_name, ftp_search_path, table)
                ftpsearch.show()
            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")

        delete_wenjian_but = tk.Button(self.bommot_frame_center, text="删除文件", command=delete_wenjian_button, font=("宋体", 13), relief="flat")
        delete_wenjian_but.place(x=415, y=2)

    # ftp下载文件
    def xiazai_wenjian(self, ftp_list, win_path, xuanzhe_win_path, bommot_frame_center, tree, ftp_search_path):
        def xiazai_wenjian_button():
            try:
                print(ftp_list[0], ftp_search_path[0], win_path[0], "三个路径————————")

                def downloadfile(ftp, remotepath, localpath):
                    bufsize = 1024  # 设置缓冲块大小
                    fp = open(localpath, 'wb')  # 以写模式在本地打开文件
                    ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)  # 接收服务器上文件并写入本地文件
                    ftp.set_debuglevel(0)  # 关闭调试
                    fp.close()  # 关闭文件

                downloadfile(ftp_list[0], ftp_search_path[0], win_path[0]+"\\"+ftp_search_path[0].split("/")[-1])

                # 更新进度条函数
                def change_schedule(now_schedule, all_schedule):
                    canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                    bommot_frame_center.update()
                    x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                    if round(now_schedule / all_schedule * 100, 2) == 100.00:
                        x.set("完==成==了")

                canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                canvas.place(x=150, y=25)
                x = tk.StringVar()
                # 进度条以及完成程度
                out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")

                tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)

                for i in range(100):
                    change_schedule(i, 99)

                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]

                wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()

                print(win_path[0]+ftp_search_path[0].split("\\")[-1],"============================")
            except:
                showinfo("错误提示", "本地路径或服务器连接异常!")

        xiazai_wenjian_but = tk.Button(self.bommot_frame_center, text="下载文件", command=xiazai_wenjian_button, font=("宋体", 13), relief="flat")
        xiazai_wenjian_but.place(x=415, y=35)

    def gexian(self):
        tk.Label(self.bommot_frame_center, text="-------------进-------------度--------------条-------------").place(x=105, y=0)
import tkinter as tk
import os
from tkinter.messagebox import showinfo
from ftp_client_alter_bug.tree.ftp_tree import FtpTree
from ftp_client_alter_bug.tree.win_tree import WinTree


class BottomMenuBarleft:

    def __init__(self, bommot_frame_left):
        self.bommot_frame_left = bommot_frame_left

    # 创建本地目录
    def win_chuangjian_mulu(self, win_path, xuanzhe_win_path, tree):
        def win_mulu_button():
            cj_mulu_win = tk.Tk()
            cj_mulu_win.geometry("300x170")

            tk.Label(cj_mulu_win, text="创建目录", font=("宋体", 17)).place(x=100, y=15)
            tk.Label(cj_mulu_win, text="目录名:", font=("宋体", 13)).place(x=30, y=60)
            mulu_entry = tk.Entry(cj_mulu_win, width=17, font=("宋体", 13))
            mulu_entry.place(x=100, y=60)

            def mulu_but():
                try:
                    mulu_name = str(mulu_entry.get())
                    os.mkdir(win_path[0] + "\\" + mulu_name)

                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]

                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()

                    # cj_mulu_win.destroy()
                except:
                    showinfo("错误提示", "未选择路径!")
                finally:
                    cj_mulu_win.destroy()

            mulu_button = tk.Button(cj_mulu_win, text="确==========定", font=("宋体", 13), command=mulu_but)
            mulu_button.place(x=80, y=105)


            cj_mulu_win.mainloop()
        win_mulu_but = tk.Button(self.bommot_frame_left, text="创建目录", font=("宋体", 13), command=win_mulu_button, relief="flat")
        win_mulu_but.place(x=10, y=2)

    # 创建本地文件
    def win_chuangjian_wenjian(self, win_path, xuanzhe_win_path, tree):

        def win_wenjian_button():
            cj_wenjian_win = tk.Tk()
            cj_wenjian_win.geometry("300x170")

            tk.Label(cj_wenjian_win, text="创建文件", font=("宋体", 17)).place(x=100, y=15)
            tk.Label(cj_wenjian_win, text="文件名:", font=("宋体", 13)).place(x=30, y=60)
            wenjian_entry = tk.Entry(cj_wenjian_win, width=17, font=("宋体", 13))
            wenjian_entry.place(x=100, y=60)

            def wenjian_but():
                try:
                    wenjian_name = str(wenjian_entry.get())
                    f = open(win_path[0] + "\\" + wenjian_name, "w")
                    f.close()

                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]

                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()

                    # cj_wenjian_win.destroy()
                except:
                    showinfo("错误提示", "未选择路径!")
                finally:
                    cj_wenjian_win.destroy()

            wenjian_button = tk.Button(cj_wenjian_win, text="确==========定", font=("宋体", 13), command=wenjian_but)
            wenjian_button.place(x=80, y=105)

        win_wenjian_but = tk.Button(self.bommot_frame_left, text="创建文件", font=("宋体", 13), command=win_wenjian_button, relief="flat")
        win_wenjian_but.place(x=10, y=35)

    # 删除目录
    def win_delete_mulu(self, win_path, xuanzhe_win_path, tree):
        def win_mulu_delete_button():
            try:
                path = win_path[0]
                # 也可以递归删除文件
                def delAll(path):
                    if os.path.isdir(path):
                        files = os.listdir(path)
                        # 遍历并删除文件
                        for file in files:
                            p = os.path.join(path, file)
                            if os.path.isdir(p):
                                # 递归
                                delAll(p)
                            else:
                                os.remove(p)
                        # 删除文件夹
                        os.rmdir(path)
                    else:
                        os.remove(path)

                delAll(path)
                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]

                wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()
            except:
                showinfo("错误提示", "未选择路径!")

        win_delete_mu_but = tk.Button(self.bommot_frame_left, text="删除目录", font=("宋体", 13), command=win_mulu_delete_button, relief="flat")
        win_delete_mu_but.place(x=115, y=2)

    # 删除文件
    def win_delete_wenjian(self, win_path, xuanzhe_win_path, tree):
        def win_wenjian_delete_button():
            try:
                path = win_path[0]

                # 也可以递归删除文件
                def delAll(path):
                    if os.path.isdir(path):
                        files = os.listdir(path)
                        # 遍历并删除文件
                        for file in files:
                            p = os.path.join(path, file)
                            if os.path.isdir(p):
                                # 递归
                                delAll(p)
                            else:
                                os.remove(p)
                        # 删除文件夹
                        os.rmdir(path)
                    else:
                        os.remove(path)

                delAll(path)
                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]

                wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()
            except:
                showinfo("错误提示", "未选择路径!")

        win_delete_wenjian_but = tk.Button(self.bommot_frame_left, text="删除文件", font=("宋体", 13), command=win_wenjian_delete_button, relief="flat")
        win_delete_wenjian_but.place(x=115, y=35)

    # 上传文件
    def shangchaung(self, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp):
        def shangchaung_button():
            try:
                def uploadfile(ftp, remotepath, localpath):
                    bufsize = 1024
                    fp = open(localpath, 'rb')
                    ftp.storbinary(r'STOR ' + rf'{remotepath}', fp, bufsize)  # 上传文件
                    ftp.set_debuglevel(0)
                    fp.close()
                print(ftp_list[0], ftp_list[0].pwd()+"\\"+win_path[0].split("\\")[-1], win_path[0], "----------==============-----------------==========")

                uploadfile(ftp_list[0], ftp_list[0].pwd()+"\\"+win_path[0].split("\\")[-1], win_path[0])

                # 更新进度条函数
                def change_schedule(now_schedule, all_schedule):
                    canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                    bommot_frame_center.update()
                    x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                    if round(now_schedule / all_schedule * 100, 2) == 100.00:
                        x.set("完==成==了")

                canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                canvas.place(x=150, y=25)
                x = tk.StringVar()
                # 进度条以及完成程度
                out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")

                tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)

                for i in range(100):
                    change_schedule(i, 99)

                if str(ftp_list[0].pwd()) != "/":
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_list[0].pwd())
                else:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("/")
            except:
                showinfo("错误提示", "本地路径或服务器连接异常!")

        shangchaung_but = tk.Button(self.bommot_frame_left, text="上传文件", font=("宋体", 13), command=shangchaung_button, relief="flat")
        shangchaung_but.place(x=220, y=2)

    # 打开文件
    def open_wenjian(self, win_path):
        def win_open_wenjian_button():
            try:
                os.startfile(rf"{win_path[0]}")
            except:
                showinfo("错误提示", "未选择路径!")

        win_open_wenjian_but = tk.Button(self.bommot_frame_left, text="打开文件", font=("宋体", 13), command=win_open_wenjian_button, relief="flat")
        win_open_wenjian_but.place(x=220, y=35)

    def gexian(self):
        tk.Label(self.bommot_frame_left, text="w|\ni|\nn|", font=("宋体", 13)).place(x=330, y=1)

import tkinter as tk
from tkinter.messagebox import showinfo

from ftp_client_alter_bug.tree.ftp_tree import FtpTree
from ftp_client_alter_bug.tree.win_tree import WinTree


class BottomMenuBarRight:

    def __init__(self, bommot_frame_right):
        self.bommot_frame_right = bommot_frame_right

    # 隔板
    def geban(self):
        tk.Label(self.bommot_frame_right, text="|f\n|t\n|p", font=("宋体", 13), relief="flat").place(x=-5, y=5)

    # 创建目录
    def ftp_chaungjian_mulu(self, ftp_path, ftp_list, tree_ftp):

        def ftp_cj_mulu_button():
            cj_win = tk.Tk()
            cj_win.geometry("300x200")
            titlte_lab = tk.Label(cj_win, text="创建目录", font=("宋体", 18))
            titlte_lab.place(x=105, y=25)

            titlte_lab = tk.Label(cj_win, text="目录名:", font=("宋体", 13))
            titlte_lab.place(x=30, y=80)

            cj_entry = tk.Entry(cj_win, width=21)
            cj_entry.place(x=100, y=80)

            def cj_button():
                try:
                    muluzhi = str(cj_entry.get()).encode()
                    ftp_list[0].mkd(muluzhi.decode())
                    print(ftp_path)
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
                finally:
                    cj_win.destroy()


                if str(ftp_list[0].pwd()) != "/":
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_list[0].pwd())
                    # cj_win.destroy()
                else:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("/")
                    # cj_win.destroy()


            cj_but = tk.Button(cj_win, text="确=======================认", font=("宋体", 13), command=cj_button)
            cj_but.place(x=20, y=130)

            cj_win.mainloop()

        ftp_cj_mulu_but = tk.Button(self.bommot_frame_right, text="创建目录", font=("宋体", 13), relief="flat", command=ftp_cj_mulu_button)
        ftp_cj_mulu_but.place(x=40, y=2)


    # 进入下级
    def ftp_jinru_xj(self, ftp_path, ftp_list, tree_ftp):
        def ftp_jinru_xj_button():
            try:
                global path
                path = ftp_path[0]

                table = tree_ftp
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                ftptree.xianshi(ftp_path[0])
            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")

        global a
        a = ftp_jinru_xj_button

        ftp_jinru_xj_but = tk.Button(self.bommot_frame_right, text="进入下级", font=("宋体", 13), relief="flat", command=ftp_jinru_xj_button)
        ftp_jinru_xj_but.place(x=40, y=35)

    # 删除目录
    def ftp_delete_mulu(self, ftp_path, ftp_list, tree_ftp):
        def ftp_delete_mulu_button():
            try:
                ftp_list[0].rmd(ftp_path[0])

                if str(ftp_list[0].pwd()) != "/":
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_list[0].pwd())
                else:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("/")
            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")


        ftp_delete_mulu_but = tk.Button(self.bommot_frame_right, text="删除目录", font=("宋体", 13), relief="flat", command=ftp_delete_mulu_button)
        ftp_delete_mulu_but.place(x=150, y=2)

    # 删除文件
    def ftp_delete_wenjian(self, ftp_path, ftp_list, tree_ftp):
        def ftp_delete_wenjian_button():
            try:

                ftp_list[0].delete(ftp_path[0])

                if str(ftp_list[0].pwd()) != "/":
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_list[0].pwd())
                else:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("/")
            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")


        ftp_delete_wenjian_but = tk.Button(self.bommot_frame_right, text="删除文件", font=("宋体", 13), relief="flat", command=ftp_delete_wenjian_button)
        ftp_delete_wenjian_but.place(x=150, y=35)

    # 下载文件
    def xiazai(self, ftp_list, ftp_path, win_path, xuanzhe_win_path, bommot_frame_center, tree):

        def xiazai_button():
            try:
                print(ftp_list[0], ftp_path[0], win_path[0], "三个路径————————")

                def downloadfile(ftp, remotepath, localpath):
                    bufsize = 1024  # 设置缓冲块大小
                    fp = open(localpath, 'wb')  # 以写模式在本地打开文件
                    ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)  # 接收服务器上文件并写入本地文件
                    ftp.set_debuglevel(0)  # 关闭调试
                    fp.close()  # 关闭文件

                downloadfile(ftp_list[0], ftp_path[0], win_path[0]+"\\"+ftp_path[0].split("/")[-1])

                # 更新进度条函数
                def change_schedule(now_schedule, all_schedule):
                    canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                    bommot_frame_center.update()
                    x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                    if round(now_schedule / all_schedule * 100, 2) == 100.00:
                        x.set("完==成==了")

                canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                canvas.place(x=150, y=25)
                x = tk.StringVar()
                # 进度条以及完成程度
                out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")

                tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)

                for i in range(100):
                    change_schedule(i, 99)

                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]

                wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()

                print(win_path[0]+ftp_path[0].split("\\")[-1],"============================")

            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")
        xiazai_but = tk.Button(self.bommot_frame_right, text="下载文件", font=("宋体", 13), relief="flat", command=xiazai_button)
        xiazai_but.place(x=250, y=2)

    # 返回上级
    def ftp_fh_sj(self, ftp_path, ftp_list, tree_ftp):

        def ftp_fh_sj_button():
            try:
                table = tree_ftp
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                ftptree.xianshi("..")
            except:
                showinfo("错误提示", "路径选择或服务器连接异常!")
        global b
        b = ftp_fh_sj_button


        ftp_fh_sj_but = tk.Button(self.bommot_frame_right, text="返回上级", font=("宋体", 13), relief="flat", command=ftp_fh_sj_button)
        ftp_fh_sj_but.place(x=250, y=35)
import os
from tkinter import ttk
import tkinter as tk

class FtpSearch:
    def __init__(self, tree_ftp, search_name, ftp_search_path, win_tree):
        self.ftp = tree_ftp
        # 搜索框的内容
        self.search_name = search_name
        self.ftp_search_path = ftp_search_path
        self.tree = win_tree

        # # 滚动条
        # sy = tk.Scrollbar(self.center_frame)
        # sy.pack(side=tk.RIGHT, fill=tk.Y)
        # sy.config(command=self.tree.yview)
        # self.tree.config(yscrollcommand=sy.set)

        # 绑定事件
        self.tree.bind("<>", self.func)
        self.tree.pack(expand=True, fill=tk.BOTH)
        self.ev = tk.Variable()


    def show(self):
        dir_res = []
        self.ftp.dir('.', dir_res.append)
        for i in dir_res:
            print(i)
            if self.search_name in i.split()[3]:
                self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[3]))


    def func(self, event):
        # widget触发事件的构建
        self.v = event.widget.selection()
        for sv in self.v:
            file = self.tree.item(sv)["text"]
            self.ev.set(file)
            apath = self.tree.item(sv)["values"][0]

            self.ftp_search_path.clear()
            self.ftp_search_path.append(apath)
            print(self.ftp_search_path)
            print(apath)
import os
from tkinter import ttk
import tkinter as tk

class WinSearch:
    def __init__(self, search_path, search_name, win_search_path, win_tree):
        self.search_path = search_path
        # 搜索框的内容
        self.search_name = search_name
        self.win_search_path = win_search_path
        self.tree = win_tree

        # # 滚动条
        # sy = tk.Scrollbar(self.center_frame)
        # sy.pack(side=tk.RIGHT, fill=tk.Y)
        # sy.config(command=self.tree.yview)
        # self.tree.config(yscrollcommand=sy.set)

        # 绑定事件
        self.tree.bind("<>", self.func)
        self.tree.pack(expand=True, fill=tk.BOTH)
        self.ev = tk.Variable()


    # 搜索关键词目录
    def search_keyword_dirs(self, root1, dirs):
        for _dir in dirs:
            if -1 != _dir.find(self.search_name) and _dir[0] != '$':
                AllDir = os.path.join(root1, _dir)
                self.tree.insert("", "end", text=AllDir, values=(AllDir,))

    # 搜索关键词文件
    def search_keyword_files(self, root, files):
        for file in files:
            if self.search_name in file:
                AllFile = os.path.join(root, file)

                self.tree.insert("", "end", text=AllFile, values=(AllFile,))

    # 搜索
    def search(self):
        curdisks = self.search_path
        # root 当前正在遍历的这个文件夹的本身的地址
        # dirs 是一个 list ,内容是该文件夹中所有的目录的名字
        # files 同样是 list , 内容是该文件夹中所有的文件
        for root, dirs, files in os.walk(curdisks):
            self.search_keyword_dirs(root, dirs)
            self.search_keyword_files(root,  files)



    def func(self, event):
        # widget触发事件的构建
        self.v = event.widget.selection()
        for sv in self.v:
            file = self.tree.item(sv)["text"]
            self.ev.set(file)
            apath = self.tree.item(sv)["values"][0]

            self.win_search_path.clear()
            self.win_search_path.append(apath)
            print(self.win_search_path)
            print(apath)


import pickle
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showinfo

from ftp_client_alter_bug.seek.ftp_search import FtpSearch
from ftp_client_alter_bug.seek.win_search import WinSearch
from ftplib import FTP
import tkinter.filedialog as fi
from ftp_client_alter_bug.tree.ftp_tree import FtpTree
from ftp_client_alter_bug.tree.win_tree import WinTree


class TopMenuBar:
    def __init__(self, top_frame, path, win, win_search_path, ftp_list, xuanzhe_win_path):
        self.top_frame = top_frame
        self.path = path
        self.win = win
        self.win_search_path = win_search_path
        self.ftp_list = ftp_list
        self.xuanzhe_win_path = xuanzhe_win_path


    # logo
    def logo(self):
        logo_lable = tk.Label(self.top_frame, text="FTP客户端", font=("华文彩云", 29), fg="green")
        logo_lable.place(x=5, y=10)

    # window目录选择按钮
    def local_mulu(self, win_path, tree):
        # 目录选择按钮的回调函数
        def mulu_button():
            self.xuanzhe_win_path.clear()
            DEF_PATH = ""
            newDir = fi.askdirectory(initialdir=DEF_PATH, title="打开目录")
            print(newDir)
            DEF_PATH = newDir
            if len(newDir) == 0:
                return
            print(DEF_PATH)
            self.xuanzhe_win_path.append(DEF_PATH)
            print(self.xuanzhe_win_path)

            table = tree
            items = table.get_children()
            [table.delete(item) for item in items]

            wintree = WinTree(self.xuanzhe_win_path[0], win_path, tree)
            wintree.show_wenjian()

        mulu_but = tk.Button(self.top_frame, text="选择本地目录", font=("宋体", 13), command=mulu_button, relief="flat")
        mulu_but.place(x=220, y=5)

    # 打开文件按钮
    def open_wenjian(self):
        def open_wenjian_button():
            pass

        open_wenjian_but = tk.Button(self.top_frame, text="选择本地文件", font=("宋体", 13), command=open_wenjian_button, relief="flat")
        open_wenjian_but.place(x=220, y=30)


    # 搜索框和其按钮
    def search_box(self, win_search_name, win_search_tree, ftp_search_path, ftp_list):
        # 本地搜索按钮的回调函数
        def local_search_button():
            try:
                win_search_name.clear()
                win_name = search_entry.get()
                win_search_name.append(win_name)

                table = win_search_tree[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                winsearch = WinSearch(self.xuanzhe_win_path[0], win_name, self.win_search_path, win_search_tree[0])
                winsearch.search()
            except:
                showinfo("错误提示", "本地路径异常!")

        # ftp搜索按钮的回调函数
        def ftp_search_button():
            try:
                win_search_name.clear()
                win_name = search_entry.get()
                win_search_name.append(win_name)

                table = win_search_tree[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                ftpsearch = FtpSearch(ftp_list[0], win_name, ftp_search_path, table)
                ftpsearch.show()
            except:
                showinfo("错误提示", "服务器连接异常!")


        search_entry = tk.Entry(self.top_frame, width="21",  font=("宋体", 15))
        search_entry.place(x=475, y=17)

        window_search = tk.Button(self.top_frame, text="本地搜索", font=("宋体", 15), command=local_search_button, relief="flat")
        window_search.place(x=350, y=17)

        ftp_search = tk.Button(self.top_frame, text="ftp搜索", font=("宋体", 15), command=ftp_search_button, relief="flat")
        ftp_search.place(x=730, y=17)

    # ip,port显示
    def name_ip(self, bieming, ip):
        name = bieming
        name_lable = tk.Label(self.top_frame, text=f"user: {name}", font=("宋体", 13))
        name_lable.place(x=850, y=5)
        ip = ip
        ip_lable = tk.Label(self.top_frame, text=f"ip: {ip}", font=("宋体", 13))
        ip_lable.place(x=1030, y=5)

    # 退出登录按钮
    def exit_login(self, ftp_tree_list, ftp_path, ftp_list):
        def exit_button():
            self.ftp_list[0].quit()
            table = ftp_tree_list[0]
            items = table.get_children()
            [table.delete(item) for item in items]
            ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
            ftptree.xianshi("/")

        exit_but = tk.Button(self.top_frame, text="退出登录", font=("宋体", 13), command=exit_button, relief="flat")
        exit_but.place(x=1100, y=30)

    # 登录按钮
    def login_in(self, ftp_path, ftp_list, ftp_tree_list):
        def login_in_button():
            wind = tk.Tk()
            wind.geometry("400x370")
            titile_lab = tk.Label(wind, text="ftp登录", font=("宋体", 19))
            titile_lab.place(x=150, y=30)

            self.ftp_list.clear()

            bieming_lab = tk.Label(wind, text="别名:", font=("宋体", 15))
            bieming_lab.place(x=60, y=90)
            bieming_entry = tk.Entry(wind, font=("宋体", 15))
            bieming_entry.place(x=130, y=90)

            user_name_lab = tk.Label(wind, text="用户名:", font=("宋体", 15))
            user_name_lab.place(x=40, y=130)
            user_name_entry = tk.Entry(wind, font=("宋体", 15))
            user_name_entry.place(x=130, y=130)

            pass_name_lab = tk.Label(wind, text="密码:", font=("宋体", 15))
            pass_name_lab.place(x=60, y=170)
            pass_name_entry = tk.Entry(wind, font=("宋体", 15))
            pass_name_entry.place(x=130, y=170)

            ip_name_lab = tk.Label(wind, text="ip:", font=("宋体", 15))
            ip_name_lab.place(x=80, y=210)
            ip_name_entry = tk.Entry(wind, font=("宋体", 15))
            ip_name_entry.place(x=130, y=210)

            port_name_lab = tk.Label(wind, text="port:", font=("宋体", 15))
            port_name_lab.place(x=60, y=250)
            port_name_entry = tk.Entry(wind, font=("宋体", 15))
            port_name_entry.place(x=130, y=250)

            def d_button():
                self.ftp_list.clear()
                bieming = str(bieming_entry.get())
                user_name = str(user_name_entry.get())
                pass_name = str(pass_name_entry.get())
                ip_name = str(ip_name_entry.get())
                port_name = int(port_name_entry.get())

                try:
                    # 打开被序列化文件
                    with open("../data/usr_info.pickle", "wb") as usr_file:
                        # 用户数据
                        usr_info = [bieming, user_name, pass_name, ip_name, port_name]
                        # 存储(序列化)数据
                        pickle.dump(usr_info, usr_file)
                except FileNotFoundError:
                        print("存储错误")

                self.name_ip(bieming, ip_name)

                self.ftp = FTP()  # 设置变量
                self.ftp.connect(ip_name, port_name)  # 连接的ftp sever和端口
                self.ftp.login(user_name, pass_name)  # 连接的用户名,密码
                self.ftp.encoding = 'GB18030'

                self.ftp_list.append(self.ftp)

                table = ftp_tree_list[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
                ftptree.xianshi("/")

                wind.destroy()


            d_but = tk.Button(wind, text="登=======================录", font=("宋体", 15), command=d_button)
            d_but.place(x=60, y=310)


            wind.mainloop()



        login_in_but = tk.Button(self.top_frame, text="登录", font=("宋体", 13), command=login_in_button, relief="flat")
        login_in_but.place(x=850, y=30)

    # 历史登录
    def lishi_login_in(self, ftp_path, ftp_list, ftp_tree_list):
        def lishi_login_button():
            self.ftp_list.clear()
            try:
                # 打开被序列化文件,会自动创建此文件
                with open("../data/usr_info.pickle", "rb+") as usr_file:
                    # 读取被序列化的文件
                    global usr_info
                    usr_info = pickle.load(usr_file)
                    print(usr_info)
            except FileNotFoundError:
                    print("读取错误")

            self.name_ip(usr_info[0], usr_info[3])

            self.ftp = FTP()  # 设置变量
            self.ftp.connect(usr_info[3], usr_info[4])  # 连接的ftp sever和端口
            self.ftp.login(usr_info[1], usr_info[2])  # 连接的用户名,密码
            self.ftp.encoding = 'GB18030'

            self.ftp_list.append(self.ftp)

            table = ftp_tree_list[0]
            items = table.get_children()
            [table.delete(item) for item in items]
            ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
            ftptree.xianshi("/")

        lishi_login_but = tk.Button(self.top_frame, text="历史登录", font=("宋体", 13), command=lishi_login_button, relief="flat")
        lishi_login_but.place(x=950, y=30)
import os
import tkinter as tk
from tkinter import ttk
from ftplib import FTP  # 加载ftp模块
import sys

class FtpTree:

    def __init__(self, ftp_path, ftp_list, tree_ftp):

        self.tree = tree_ftp
        self.num = 0

        self.ftp_list = ftp_list
        self.ftp_path = ftp_path


        # # 滚动条
        # sy = tk.Scrollbar(self.right_frame)
        # sy.pack(side=tk.LEFT, fill=tk.Y)
        # sy.config(command=self.tree.yview)
        # self.tree.config(yscrollcommand=sy.set)

        # 绑定事件
        self.tree.bind("<>", self.func)
        self.tree.pack(expand=True, fill=tk.BOTH)
        self.ev = tk.Variable()
        print(self.ev)

    def xianshi(self, path_ftp):

        self.ftp = self.ftp_list[0]
        self.ftp.cwd(path_ftp)
        self.num += 1
        dir_res = []
        self.ftp.dir('.', dir_res.append)
        for i in dir_res:
            if i.split()[2] == "":
                self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[0], i.split()[2]))
            else:
                self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[0], ""))

    def func(self, event):
        # widget触发事件的构建
        self.v = event.widget.selection()
        for sv in self.v:
            self.file = self.tree.item(sv)["text"]
            self.ev.set(self.file)

            self.ftp_path.clear()
            self.ftp_path.append(self.file)
            print(self.ftp_path)
            print(self.file)



import os
import tkinter as tk
from tkinter import ttk

class WinTree:

    def __init__(self, path, win_path, tree):
        self.path = path
        self.win_path = win_path
        self.tree = tree

        # # 滚动条
        # sy = tk.Scrollbar(self.left_frame)
        # sy.pack(side=tk.RIGHT, fill=tk.Y)
        # sy.config(command=self.tree.yview)
        # self.tree.config(yscrollcommand=sy.set)

        # 绑定事件
        self.tree.bind("<>", self.func)
        self.tree.pack(expand=True, fill=tk.BOTH)
        self.ev = tk.Variable()
        print(self.ev)

    def show_wenjian(self):
        self.root = self.tree.insert("", "end", text=self.getlastpath(self.path, ), open=True, values=(self.path,))
        self.loadtree(self.root, self.path)

    def func(self, event):
        # widget触发事件的构建
        self.v = event.widget.selection()
        for sv in self.v:
            file = self.tree.item(sv)["text"]
            self.ev.set(file)
            apath = self.tree.item(sv)["values"][0]

            self.win_path.clear()
            self.win_path.append(apath)
            print(self.win_path)
            print(apath)

    def loadtree(self, parent, parentPath):
        for FileName in os.listdir(parentPath):
            absPath = os.path.join(parentPath, FileName)
            if ("$" in absPath) == False:
                # 插入树枝
                treey = self.tree.insert(parent, "end", text=self.getlastpath(absPath), values=(absPath, ))

                # 判断是否是目录
                if os.path.isdir(absPath):

                    self.loadtree(treey, absPath)

    def getlastpath(self, path):

        pathList = os.path.split(path)
        return pathList[-1]

from tkinter.messagebox import showinfo

import windnd
import tkinter as tk
from ftp_client_alter_bug.tree.ftp_tree import FtpTree


class FtpDrag():
    def __init__(self, right_frame, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp):
        self.right_frame = right_frame
        self.ftp_path = ftp_path
        self.ftp_list = ftp_list
        self.win_path = win_path
        self.bommot_frame_center = bommot_frame_center
        self.tree_ftp = tree_ftp

    def win_file(self, files):
        msg = "\n".join((item.decode("gbk") for item in files))
        print(msg)
        # with open(msg, mode="rb+") as re:
        #     buffer = re.read()
        # with open(self.win_path[0] + "\\" + msg.split("\\")[-1], mode="wb+") as wr:
        #     wr.write(buffer)
        try:
            def uploadfile(ftp, remotepath, localpath):
                bufsize = 1024
                fp = open(localpath, 'rb')
                ftp.storbinary(r'STOR ' + rf'{remotepath}', fp, bufsize)  # 上传文件
                ftp.set_debuglevel(0)
                fp.close()


            uploadfile(self.ftp_list[0], self.ftp_list[0].pwd() + "\\" + msg.split("\\")[-1], msg)

            # 更新进度条函数
            def change_schedule(now_schedule, all_schedule):
                canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                self.bommot_frame_center.update()
                x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                if round(now_schedule / all_schedule * 100, 2) == 100.00:
                    x.set("完==成==了")

            canvas = tk.Canvas(self.bommot_frame_center, width=110, height=30, bg="white")
            canvas.place(x=150, y=25)
            x = tk.StringVar()
            # 进度条以及完成程度
            out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
            fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")

            tk.Label(self.bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)

            for i in range(100):
                change_schedule(i, 99)

            if str(self.ftp_list[0].pwd()) != "/":
                table = self.tree_ftp
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(self.ftp_path, self.ftp_list, self.tree_ftp)
                ftptree.xianshi(self.ftp_list[0].pwd())
            else:
                table = self.tree_ftp
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(self.ftp_path, self.ftp_list, self.tree_ftp)
                ftptree.xianshi("/")
        except:
            showinfo("错误提示", "服务器连接异常!")

    def execute(self):
        windnd.hook_dropfiles(self.right_frame, func=self.win_file)
from tkinter.messagebox import showinfo

import windnd
from ftp_client_alter_bug.tree.win_tree import WinTree


class WinDrag():
    def __init__(self, left_frame, win_path, xuanzhe_win_path, tree):
        self.left_frame = left_frame
        self.win_path = win_path
        self.xuanzhe_win_path = xuanzhe_win_path
        self.tree = tree

    def win_file(self, files):
        msg = "\n".join((item.decode("gbk") for item in files))
        print(msg)
        try:
            with open(msg, mode="rb+") as re:
                buffer = re.read()
            with open(self.win_path[0] + "\\" + msg.split("\\")[-1], mode="wb+") as wr:
                wr.write(buffer)
            table = self.tree
            items = table.get_children()
            [table.delete(item) for item in items]

            wintree = WinTree(self.xuanzhe_win_path[0], self.win_path, self.tree)
            wintree.show_wenjian()
        except:
            showinfo("错误提示", "未选择本地路径!")

    def execute(self):
        windnd.hook_dropfiles(self.left_frame, func=self.win_file)

你可能感兴趣的:(原创项目,python,ftp)