python实现ftp服务器(使用wxpython实现GUI界面)

开发背景:

有时需要在局域网传输文件,总是要用U盘传输,要是多个人都需要同样的文件,U盘就有点麻烦了,Windows上的文件共享配置步骤很少,但是经常因为各种原因失败,又要检查来检查去的。于是考虑到通过FTP协议来传输文件,但是出名的FTP服务器软件类似Serv-U 这种,功能是很强大,但是配置也很多,我只是临时传输下文件,希望可以免安装,一键启动FTP,一键关闭FTP。于是就想使用python实现FTP服务器,再打包成exe文件。

开发环境:

win 7 64位,Python 3.6.2,pyftpdlib,wxpython,pyinstaller 3.3.1

具体思路:

通过pyftpdlib库实现FTP 功能ftpserver.py,使用wxpython实现GUI界面wxgui.py,在wxgui.py上生成配置文件config.ini,ftpserver.py再获取config.ini中的信息启动FTP,最后使用pyinstaller打包成exe可执行文件。

软件截图:

不过刚开发好的软件,应该有挺多BUG的,以后使用过程中再慢慢改进。
打开软件:
python实现ftp服务器(使用wxpython实现GUI界面)
选择FTP目录:
python实现ftp服务器(使用wxpython实现GUI界面)
启动FTP:
python实现ftp服务器(使用wxpython实现GUI界面)

具体源代码:

实现FTP功能代码ftpserver.py:

# coding:utf-8
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import logging
import configparser
import os
def ftpd():
    authorizer = DummyAuthorizer()
    if getconfig('anonymous')=='True':
        #添加匿名用户
        authorizer.add_anonymous(getconfig('dir'),perm='elradfmwM')
    else:    
        #添加用户,需要账号和密码登录
        authorizer.add_user(getconfig('user'), getconfig('password'), getconfig('dir'), perm='elradfmwM')
    handler = FTPHandler#初始化处理客户端命令的类
    handler.authorizer = authorizer#选择登录方式(是否匿名)
    logging.basicConfig(filename='ftpd.log', level=logging.INFO) #日志信息写入ftpd.log
    address = ('0.0.0.0', getconfig('port'))#设置服务器的监听地址和端口
    server = FTPServer(address, handler)
    server.max_cons = 256                              #给链接设置限制
    server.max_cons_per_ip = 5
    server.serve_forever()                             # 启动FTP

def getconfig(v):
    #获取config.ini配置文件的信息
    config = configparser.ConfigParser()
    config.read('config.ini')
    return config.get('ftpd',v)
if __name__ == '__main__':
    ftpd()

实现GUI界面代码wxgui.py:

# -*- coding:utf-8 -*-
import wx
import os
import sys
import configparser
import ftpserver
import time
import threading
import socket
def onclick(event): #选择FTP目录
    dlg=wx.DirDialog(window,'选择共享目录')
    if dlg.ShowModal() == wx.ID_OK:
        dirtext.SetValue(dlg.GetPath())

def onclose(event):  #退出事件
    if startbutton.GetLabel()=='关闭FTP':
        dlg1 = wx.MessageDialog(None, "FTP正在运行,确认退出吗?", "退出", wx.YES_NO | wx.ICON_EXCLAMATION)
        if dlg1.ShowModal()==wx.ID_YES:
            sys.exit()
    else:
        sys.exit()

def startftp(event): #点击 启动FTP 按钮事件
    global t
    if startbutton.GetLabel()=='启动FTP':
        startbutton.SetLabel('关闭FTP')
        #把FTP启动信息写入config.ini配置文件中
        config=configparser.ConfigParser()
        config.add_section('ftpd')
        config.set('ftpd','anonymous',str(not check.GetValue()))
        config.set('ftpd','user',usertext.GetValue())
        config.set('ftpd','password',passtext.GetValue())
        config.set('ftpd','port',porttext.GetValue())
        config.set('ftpd','dir',dirtext.GetValue())
        with open('config.ini','w') as conf:
            config.write(conf)
        time.sleep(1)
        #创建线程启动FTP
        t=threading.Thread(target=ftpserver.ftpd)
        t.setDaemon(True)        
        t.start()
        iplist=socket.gethostbyname_ex(socket.gethostname())[2]
        ftpurl=''
        if iplist :
            for ip in iplist:
                ftpurl+='FTP地址:ftp://'+ip+':'+porttext.GetValue()+'\n'
        urllabel.SetLabel(ftpurl)
    else:
        dlg1 = wx.MessageDialog(None, "FTP正在运行,确认退出吗?", "退出", wx.YES_NO | wx.ICON_EXCLAMATION)
        if dlg1.ShowModal()==wx.ID_YES:
            sys.exit()
def onchecked(event): #复选框事件
    usertext.SetEditable(event.IsChecked())
    passtext.SetEditable(event.IsChecked())

app = wx.App()#实例化wx.App
#创建顶级窗口,并且窗口不可改变尺寸
window = wx.Frame(None,title = "FTP服务器", size = (390, 260), pos=(400,300),style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
#绑定退出事件
window.Bind(wx.EVT_CLOSE,onclose)
#创建panel
panel = wx.Panel(window)
font = wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL)
#创建复选框,并绑定事件
check=wx.CheckBox(panel,-1,'使用账户密码登录',pos=(20,20),size=(200,-1))
check.SetFont(font)
window.Bind(wx.EVT_CHECKBOX,onchecked)
#创建静态文本和文本输入框
userlabel = wx.StaticText(panel, label = "用户名:", pos=(35,45))
userlabel.SetFont(font)
usertext = wx.TextCtrl(panel,-1,'',size=(95,20),pos=(90,42),style = wx.TE_READONLY) 
passlabel = wx.StaticText(panel, label = "密码:",pos=(195,45))
passlabel.SetFont(font)
passtext = wx.TextCtrl(panel,-1,'',size=(95,20),pos=(235,42),style = wx.TE_PASSWORD)
passtext.SetEditable(False)
dirlabel = wx.StaticText(panel, label = "FTP目录:",pos=(23,72))
dirlabel.SetFont(font)
dirtext = wx.TextCtrl(panel,-1,os.getcwd(),size=(215,20),pos=(88,70),style = wx.TE_READONLY)
#创建按钮,并且绑定按钮事件
button=wx.Button(panel,-1,'更改',pos=(310,70),size=(40,20))
button.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.NORMAL))
window.Bind(wx.EVT_BUTTON,onclick,button)
portlabel = wx.StaticText(panel, label = "FTP端口:",pos=(23,104))
portlabel.SetFont(font)
porttext = wx.TextCtrl(panel,-1,'21',size=(51,20),pos=(88,102))
startbutton=wx.Button(panel,-1,'启动FTP',pos=(160,130),size=(70,30))
startbutton.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL))
window.Bind(wx.EVT_BUTTON,startftp,startbutton)
#加载配置文件,使程序恢复到退出前的界面
if os.path.isfile('config.ini'):
    if ftpserver.getconfig('anonymous')=='False':
        check.SetValue(1)
        usertext.SetEditable(1)
        passtext.SetEditable(1)
    usertext.SetValue(ftpserver.getconfig('user'))
    passtext.SetValue(ftpserver.getconfig('password'))
    porttext.SetValue(ftpserver.getconfig('port'))
    dirtext.SetValue(ftpserver.getconfig('dir'))
urllabel = wx.StaticText(panel, label = "", pos=(80, 170))
urllabel.SetFont(font)
window.Show(True)#窗口可见
app.MainLoop() #主循环,处理事件

使用pyinstaller打包

如果顺利的话,两条命令就可以成功打包了,反正我是没那么顺利的了
pip安装pyinstaller
pip install pyinstaller
开始打包:
pyinstaller -F wxgui.py -w
-F 参数:是生成单个可执行文件
-w参数:因为我的是GUI程序,所以我使用这参数去掉命令行窗口
生成的文件:
python实现ftp服务器(使用wxpython实现GUI界面)

问题总结:

这次开发这个小项目中遇到了个问题,百度谷歌都找不到解决的办法。
程序创建个线程去启动FTP服务,当我想要停止FTP服务时,在不退出程序的情况下该如何去停止FTP服务?

猜你喜欢

转载自blog.51cto.com/eddy72/2113157