python,Pyqt5 实现FTP服务器与客户端文件上传,下载

前言

ftp协议即文件传输协议,人生苦短,我用python,对于编程新手写个ftp服务器及客户端,python绝对是很好的选择,本人用python pyftpdlib模块编写了ftp服务器,也使用pyqt5编写了简单的FTP客户端实现ftp服务器链接文件上传,下载等功能。

一.FTP链接服务端,文件读取上传,下载功能展示

1.链接FTP服务器

填写ftp服务器链接主机ip地址,用户名,密码,端口号,点击链接按钮,看到打印链接成功信息及成功链接上ftp服务器,可在下方查看ftp服务器文件。

2.上传文件到FTP服务器

右击链接FTP服务器的文件点击上传按钮,可选择要上传的文件

选择要上传的文件:

 看到如下图打印上传文件成功信息,即文件成功上传到Ftp服务器,上传成功后可以在下方Ftp服务器的文件夹中看到上传的文件。

3.下载文件到本地

右击链接FTP服务器的文件点击下载按钮:

看到如下图打印下载文件成功信息,即文件成功从Ftp服务器下载到本地,可以在本地打开下载的文件: 

二.ftp服务端主要代码

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

class FtpServer:

    def ftpStart(self):
        # 实例化虚拟用户,这是FTP验证首要条件
        authorizer = DummyAuthorizer()

        authorizer.add_user('user', '12345', 'D:/ftpFile', perm='elradfmw')
        # 添加匿名用户 只需要路径
        authorizer.add_anonymous('D:/ftpFile/test')

        handler = FTPHandler
        handler.authorizer = authorizer
        # 添加被动端口范围
        handler.passive_ports = range(2000, 8333)
        # 监听ip 和 端口,使用21端口
        server = FTPServer(('127.0.0.1', 21), handler)
        # server.set_pasv(False)
        # 开始服务
        server.serve_forever()

 三.客户端主要代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'FtpGui.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.
from tqdm import tqdm
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_DIR)
from FtpClientOperation import FtpClient
from PyQt5.QtGui import QIcon,QCursor
from PyQt5.QtCore import Qt, QUrl, QCoreApplication
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox, QMenu, QAction, QFileDialog, QProgressBar, QProgressDialog

from utils.StringUtils import isNull,isNotNull

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        self.MainWindow = MainWindow
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(384, 489)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("../image/icon/FTP.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.toolButton = QtWidgets.QToolButton(self.centralwidget)
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap("../image/icon/FTP.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.toolButton.setIcon(icon1)
        self.toolButton.setObjectName("toolButton")
        self.horizontalLayout_3.addWidget(self.toolButton)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.horizontalLayout.addWidget(self.lineEdit_3)
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout.addWidget(self.lineEdit_2)
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setObjectName("label_3")
        self.horizontalLayout.addWidget(self.label_3)
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setObjectName("label_4")
        self.horizontalLayout.addWidget(self.label_4)
        self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.horizontalLayout.addWidget(self.lineEdit_4)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.textBrowser.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.textBrowser.setLineWrapMode(0)
        self.textBrowser.setObjectName("textBrowser")
        self.verticalLayout.addWidget(self.textBrowser)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setObjectName("label_5")
        self.horizontalLayout_2.addWidget(self.label_5)
        self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_5.setObjectName("lineEdit_5")
        self.horizontalLayout_2.addWidget(self.lineEdit_5)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
        self.treeWidget.setColumnCount(4)
        self.treeWidget.setObjectName("treeWidget")
        item_0 = QtWidgets.QTreeWidgetItem(self.treeWidget)
        self.horizontalLayout_4.addWidget(self.treeWidget)
        self.verticalLayout.addLayout(self.horizontalLayout_4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(self.connectFtp)
        self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)  # 打开右键菜单的策略
        self.treeWidget.customContextMenuRequested.connect(self.treeWidgetItem_fun)  # 绑定事件
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "FTP Client"))
        self.toolButton.setText(_translate("MainWindow", "file"))
        self.label.setText(_translate("MainWindow", "主机:"))
        self.label_2.setText(_translate("MainWindow", "用户名:"))
        self.label_3.setText(_translate("MainWindow", "密码:"))
        self.label_4.setText(_translate("MainWindow", "端口号:"))
        self.lineEdit_3.setText(_translate("MainWindow", "127.0.0.1"))
        self.lineEdit_2.setText(_translate("MainWindow", "user"))
        self.lineEdit.setText(_translate("MainWindow", "12345"))
        self.lineEdit.setEchoMode(QtWidgets.QLineEdit.Password)
        self.lineEdit_4.setText(_translate("MainWindow", "21"))
        self.pushButton.setText(_translate("MainWindow", "链接"))
        self.label_5.setText(_translate("MainWindow", "链接远程站点:"))
        self.treeWidget.headerItem().setText(0, _translate("MainWindow", "文件名"))
        self.treeWidget.headerItem().setText(1, _translate("MainWindow", "文件大小"))
        self.treeWidget.headerItem().setText(2, _translate("MainWindow", "文件类型"))
        self.treeWidget.headerItem().setText(3, _translate("MainWindow", "最新修改时间"))
        __sortingEnabled = self.treeWidget.isSortingEnabled()
        self.treeWidget.setSortingEnabled(False)
        self.treeWidget.topLevelItem(0).setText(0, _translate("MainWindow", "/"))
        self.treeWidget.topLevelItem(0).setText(2, _translate("MainWindow", "directory"))
        self.treeWidget.topLevelItem(0).setIcon(0, QIcon('../image/icon/folder.png'))
        self.treeWidget.setSortingEnabled(__sortingEnabled)
    def connectFtp(self):
        addr=self.lineEdit_3.text();
        userName=self.lineEdit_2.text();
        password=self.lineEdit.text();
        port=self.lineEdit.text()
        print("哈哈"+addr+","+userName+","+password)
        if isNull(addr)==True or isNull(userName)==True or isNull(password)==True:
            QMessageBox.information(self.MainWindow, '警告', 'ftp ip地址或用户名或密码不能为空,请检查!', QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
        else:
            self.ftpOperation=FtpClient(addr,int(port))
            ftpclient=self.ftpOperation.ftp_connect(userName,password)
            print("ftp:"+ftpclient.getwelcome())
            self.textBrowser.append(ftpclient.getwelcome())
            self.textBrowser.append("ftp:"+addr+" 链接成功!")
            ftpPath=ftpclient.pwd()
            self.lineEdit_5.setText(ftpPath)
            _translate = QtCore.QCoreApplication.translate
            print(ftpPath)
            self.treeWidget.topLevelItem(0).setText(0, _translate("MainWindow", ftpPath))

            top_file_list=ftpclient.getdirs(ftpPath)
            for i in range(len(top_file_list)):
                self.treeWidget.topLevelItem(0).addChild(QtWidgets.QTreeWidgetItem())
                #['20221104135530', 'perm=radfw', 'size=53990', 'type=file']
                self.treeWidget.topLevelItem(0).child(i).setText(0, _translate("MainWindow", top_file_list[i]))
                modify_time = ftpclient.get_modify_time(ftpPath+top_file_list[i]).split(";")
                self.treeWidget.topLevelItem(0).child(i).setText(1, _translate("MainWindow", modify_time[2][5:-1]))
                self.treeWidget.topLevelItem(0).child(i).setText(3, _translate("MainWindow", modify_time[0]))
                if ftpclient.checkFileDir(ftpPath+top_file_list[i]) == "Dir":
                    self.treeWidget.topLevelItem(0).child(i).setText(2, _translate("MainWindow", "directory"))
                    self.treeWidget.topLevelItem(0).child(i).setIcon(0, QIcon('../image/icon/folder.png'))
                    self.addTreeItem(ftpclient, ftpPath + top_file_list[i], self.treeWidget.topLevelItem(0).child(i),
                                     _translate)
                else:
                    self.treeWidget.topLevelItem(0).child(i).setIcon(0,QIcon('../image/icon/file.png'))
                    self.treeWidget.topLevelItem(0).child(i).setText(2, _translate("MainWindow", "file"))

            print(top_file_list)
    def addTreeItem(self,ftpclient,filePath,parentItem,_translate):
        file_list = ftpclient.getdirs(filePath)
        for i in range(len(file_list)):
            parentItem.addChild(QtWidgets.QTreeWidgetItem())
            parentItem.child(i).setText(0, _translate("MainWindow", file_list[i]))
            modify_time = ftpclient.get_modify_time(filePath + "/" + file_list[i]).split(";")
            parentItem.child(i).setText(1, _translate("MainWindow", modify_time[2][5:-1]))
            parentItem.child(i).setText(3, _translate("MainWindow", modify_time[0]))
            if ftpclient.checkFileDir(filePath+"/"+file_list[i]) == "Dir":
                parentItem.child(i).setIcon(0, QIcon('../image/icon/folder.png'))
                parentItem.child(i).setText(2,_translate("MainWindow", "directory" ))
                self.addTreeItem(ftpclient, filePath +"/"+ file_list[i], parentItem.child(i),
                                 _translate)
            else:
                parentItem.child(i).setIcon(0, QIcon('../image/icon/file.png'))
                parentItem.child(i).setText(2, _translate("MainWindow", "file"))

    # 定义treewidget中item右键界面
    def treeWidgetItem_fun(self, pos):
        item = self.treeWidget.currentItem()
        item1 = self.treeWidget.itemAt(pos)

        if item != None and item1 != None:  # 判断菜单是否为空
            popMenu = QMenu()
            if item.text(2)=="directory":
                self.upload=popMenu.addAction(QAction(u'上传', self.treeWidget))
            else:
                self.download=popMenu.addAction(QAction(u'下载', self.treeWidget))
            popMenu.triggered[QAction].connect(self.processtrigger)  # 右键点击清空之后执行的操作
            popMenu.exec_(QCursor.pos())  # 执行之后菜单可以显示

    # 右键点击清空之后执行的操作
    def processtrigger(self, q):
        # 相应的处理
        command = q.text()
        item = self.treeWidget.currentItem()
        filePath=self.getLocation(item)
        print(filePath)
        if command == "上传":
            self.ftpOperation.ftpClient.cwd(filePath)
            fileUrl = QFileDialog.getOpenFileUrl(None, '打开文件', QUrl('.'),'所有文件(*.*);;Python文件(*.py);;图片(*.png *.jpg)')
            if fileUrl[0]!=None and isNotNull(fileUrl[0].path()):
                pathFile=fileUrl[0].path().strip("/")
                self.textBrowser.append("上传文件:"+pathFile)
                self.textBrowser.append("正在上传文件:" +pathFile+ " 到" + filePath)
                res=self.ftpOperation.upload(pathFile)
                self.progressDialog(5000)
                self.textBrowser.append("上传文件成功,文件路径:" + filePath+"/"+os.path.basename(pathFile))
            else:
                QMessageBox.information(self.MainWindow, '警告', '未选择文件!',
                                        QMessageBox.Ok | QMessageBox.Close,
                                        QMessageBox.Close)

        elif command == "下载":
            if item.parent():
                self.ftpOperation.ftpClient.cwd(self.getLocation(item.parent()))
            self.textBrowser.append("正在下载文件" + filePath)
            res=self.ftpOperation.download(item.text(0))
            self.textBrowser.append("下载文件成功,文件路径:" + res)
    def progressDialog(self,elapsed):
        dlg = QProgressDialog()
        dlg.setWindowTitle('等待......')
        dlg.setWindowModality(Qt.WindowModal)
        dlg.show()
        for val in range(elapsed):
            dlg.setValue(val)
            QCoreApplication.processEvents()
            if dlg.wasCanceled():
                break
        dlg.setValue(elapsed)




    def getLocation(self, item):
        path=item.text(0)
        print(path)
        if item.parent():
            temp = item.parent()
            parentPath=temp.text(0)
            print(path)
            if parentPath=='/':
                path=parentPath+path
            if temp.parent():
              path=self.getLocation(temp)+"/"+path
        return path




if __name__=='__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    widget = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(widget)
    widget.show()
    sys.exit(app.exec_())

项目源码下载链接:python,Pyqt5 实现FTP服务器与客户端文件上传,下载;有问题可以直接csdn问我或评论提问

  • 0
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雁过留声--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值