当前位置:   article > 正文

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

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服务端主要代码

  1. from pyftpdlib.authorizers import DummyAuthorizer
  2. from pyftpdlib.handlers import FTPHandler
  3. from pyftpdlib.servers import FTPServer
  4. class FtpServer:
  5. def ftpStart(self):
  6. # 实例化虚拟用户,这是FTP验证首要条件
  7. authorizer = DummyAuthorizer()
  8. authorizer.add_user('user', '12345', 'D:/ftpFile', perm='elradfmw')
  9. # 添加匿名用户 只需要路径
  10. authorizer.add_anonymous('D:/ftpFile/test')
  11. handler = FTPHandler
  12. handler.authorizer = authorizer
  13. # 添加被动端口范围
  14. handler.passive_ports = range(2000, 8333)
  15. # 监听ip 和 端口,使用21端口
  16. server = FTPServer(('127.0.0.1', 21), handler)
  17. # server.set_pasv(False)
  18. # 开始服务
  19. server.serve_forever()

 三.客户端主要代码

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'FtpGui.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.15.4
  5. #
  6. # WARNING: Any manual changes made to this file will be lost when pyuic5 is
  7. # run again. Do not edit this file unless you know what you are doing.
  8. from tqdm import tqdm
  9. import os
  10. import sys
  11. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  12. sys.path.insert(0, BASE_DIR)
  13. from FtpClientOperation import FtpClient
  14. from PyQt5.QtGui import QIcon,QCursor
  15. from PyQt5.QtCore import Qt, QUrl, QCoreApplication
  16. from PyQt5 import QtCore, QtGui, QtWidgets
  17. from PyQt5.QtWidgets import QMessageBox, QMenu, QAction, QFileDialog, QProgressBar, QProgressDialog
  18. from utils.StringUtils import isNull,isNotNull
  19. class Ui_MainWindow(object):
  20. def setupUi(self, MainWindow):
  21. self.MainWindow = MainWindow
  22. MainWindow.setObjectName("MainWindow")
  23. MainWindow.resize(384, 489)
  24. icon = QtGui.QIcon()
  25. icon.addPixmap(QtGui.QPixmap("../image/icon/FTP.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
  26. MainWindow.setWindowIcon(icon)
  27. self.centralwidget = QtWidgets.QWidget(MainWindow)
  28. self.centralwidget.setObjectName("centralwidget")
  29. self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
  30. self.verticalLayout.setObjectName("verticalLayout")
  31. self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
  32. self.horizontalLayout_3.setObjectName("horizontalLayout_3")
  33. self.toolButton = QtWidgets.QToolButton(self.centralwidget)
  34. icon1 = QtGui.QIcon()
  35. icon1.addPixmap(QtGui.QPixmap("../image/icon/FTP.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
  36. self.toolButton.setIcon(icon1)
  37. self.toolButton.setObjectName("toolButton")
  38. self.horizontalLayout_3.addWidget(self.toolButton)
  39. self.verticalLayout.addLayout(self.horizontalLayout_3)
  40. self.horizontalLayout = QtWidgets.QHBoxLayout()
  41. self.horizontalLayout.setObjectName("horizontalLayout")
  42. self.label = QtWidgets.QLabel(self.centralwidget)
  43. self.label.setObjectName("label")
  44. self.horizontalLayout.addWidget(self.label)
  45. self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
  46. self.lineEdit_3.setObjectName("lineEdit_3")
  47. self.horizontalLayout.addWidget(self.lineEdit_3)
  48. self.label_2 = QtWidgets.QLabel(self.centralwidget)
  49. self.label_2.setObjectName("label_2")
  50. self.horizontalLayout.addWidget(self.label_2)
  51. self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
  52. self.lineEdit_2.setObjectName("lineEdit_2")
  53. self.horizontalLayout.addWidget(self.lineEdit_2)
  54. self.label_3 = QtWidgets.QLabel(self.centralwidget)
  55. self.label_3.setObjectName("label_3")
  56. self.horizontalLayout.addWidget(self.label_3)
  57. self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
  58. self.lineEdit.setObjectName("lineEdit")
  59. self.horizontalLayout.addWidget(self.lineEdit)
  60. self.label_4 = QtWidgets.QLabel(self.centralwidget)
  61. self.label_4.setObjectName("label_4")
  62. self.horizontalLayout.addWidget(self.label_4)
  63. self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget)
  64. self.lineEdit_4.setObjectName("lineEdit_4")
  65. self.horizontalLayout.addWidget(self.lineEdit_4)
  66. self.pushButton = QtWidgets.QPushButton(self.centralwidget)
  67. self.pushButton.setObjectName("pushButton")
  68. self.horizontalLayout.addWidget(self.pushButton)
  69. self.verticalLayout.addLayout(self.horizontalLayout)
  70. self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
  71. self.textBrowser.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
  72. self.textBrowser.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
  73. self.textBrowser.setLineWrapMode(0)
  74. self.textBrowser.setObjectName("textBrowser")
  75. self.verticalLayout.addWidget(self.textBrowser)
  76. self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
  77. self.horizontalLayout_2.setObjectName("horizontalLayout_2")
  78. self.label_5 = QtWidgets.QLabel(self.centralwidget)
  79. self.label_5.setObjectName("label_5")
  80. self.horizontalLayout_2.addWidget(self.label_5)
  81. self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget)
  82. self.lineEdit_5.setObjectName("lineEdit_5")
  83. self.horizontalLayout_2.addWidget(self.lineEdit_5)
  84. self.verticalLayout.addLayout(self.horizontalLayout_2)
  85. self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
  86. self.horizontalLayout_4.setObjectName("horizontalLayout_4")
  87. self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
  88. self.treeWidget.setColumnCount(4)
  89. self.treeWidget.setObjectName("treeWidget")
  90. item_0 = QtWidgets.QTreeWidgetItem(self.treeWidget)
  91. self.horizontalLayout_4.addWidget(self.treeWidget)
  92. self.verticalLayout.addLayout(self.horizontalLayout_4)
  93. MainWindow.setCentralWidget(self.centralwidget)
  94. self.statusbar = QtWidgets.QStatusBar(MainWindow)
  95. self.statusbar.setObjectName("statusbar")
  96. MainWindow.setStatusBar(self.statusbar)
  97. self.retranslateUi(MainWindow)
  98. self.pushButton.clicked.connect(self.connectFtp)
  99. self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) # 打开右键菜单的策略
  100. self.treeWidget.customContextMenuRequested.connect(self.treeWidgetItem_fun) # 绑定事件
  101. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  102. def retranslateUi(self, MainWindow):
  103. _translate = QtCore.QCoreApplication.translate
  104. MainWindow.setWindowTitle(_translate("MainWindow", "FTP Client"))
  105. self.toolButton.setText(_translate("MainWindow", "file"))
  106. self.label.setText(_translate("MainWindow", "主机:"))
  107. self.label_2.setText(_translate("MainWindow", "用户名:"))
  108. self.label_3.setText(_translate("MainWindow", "密码:"))
  109. self.label_4.setText(_translate("MainWindow", "端口号:"))
  110. self.lineEdit_3.setText(_translate("MainWindow", "127.0.0.1"))
  111. self.lineEdit_2.setText(_translate("MainWindow", "user"))
  112. self.lineEdit.setText(_translate("MainWindow", "12345"))
  113. self.lineEdit.setEchoMode(QtWidgets.QLineEdit.Password)
  114. self.lineEdit_4.setText(_translate("MainWindow", "21"))
  115. self.pushButton.setText(_translate("MainWindow", "链接"))
  116. self.label_5.setText(_translate("MainWindow", "链接远程站点:"))
  117. self.treeWidget.headerItem().setText(0, _translate("MainWindow", "文件名"))
  118. self.treeWidget.headerItem().setText(1, _translate("MainWindow", "文件大小"))
  119. self.treeWidget.headerItem().setText(2, _translate("MainWindow", "文件类型"))
  120. self.treeWidget.headerItem().setText(3, _translate("MainWindow", "最新修改时间"))
  121. __sortingEnabled = self.treeWidget.isSortingEnabled()
  122. self.treeWidget.setSortingEnabled(False)
  123. self.treeWidget.topLevelItem(0).setText(0, _translate("MainWindow", "/"))
  124. self.treeWidget.topLevelItem(0).setText(2, _translate("MainWindow", "directory"))
  125. self.treeWidget.topLevelItem(0).setIcon(0, QIcon('../image/icon/folder.png'))
  126. self.treeWidget.setSortingEnabled(__sortingEnabled)
  127. def connectFtp(self):
  128. addr=self.lineEdit_3.text();
  129. userName=self.lineEdit_2.text();
  130. password=self.lineEdit.text();
  131. port=self.lineEdit.text()
  132. print("哈哈"+addr+","+userName+","+password)
  133. if isNull(addr)==True or isNull(userName)==True or isNull(password)==True:
  134. QMessageBox.information(self.MainWindow, '警告', 'ftp ip地址或用户名或密码不能为空,请检查!', QMessageBox.Ok | QMessageBox.Close,
  135. QMessageBox.Close)
  136. else:
  137. self.ftpOperation=FtpClient(addr,int(port))
  138. ftpclient=self.ftpOperation.ftp_connect(userName,password)
  139. print("ftp:"+ftpclient.getwelcome())
  140. self.textBrowser.append(ftpclient.getwelcome())
  141. self.textBrowser.append("ftp:"+addr+" 链接成功!")
  142. ftpPath=ftpclient.pwd()
  143. self.lineEdit_5.setText(ftpPath)
  144. _translate = QtCore.QCoreApplication.translate
  145. print(ftpPath)
  146. self.treeWidget.topLevelItem(0).setText(0, _translate("MainWindow", ftpPath))
  147. top_file_list=ftpclient.getdirs(ftpPath)
  148. for i in range(len(top_file_list)):
  149. self.treeWidget.topLevelItem(0).addChild(QtWidgets.QTreeWidgetItem())
  150. #['20221104135530', 'perm=radfw', 'size=53990', 'type=file']
  151. self.treeWidget.topLevelItem(0).child(i).setText(0, _translate("MainWindow", top_file_list[i]))
  152. modify_time = ftpclient.get_modify_time(ftpPath+top_file_list[i]).split(";")
  153. self.treeWidget.topLevelItem(0).child(i).setText(1, _translate("MainWindow", modify_time[2][5:-1]))
  154. self.treeWidget.topLevelItem(0).child(i).setText(3, _translate("MainWindow", modify_time[0]))
  155. if ftpclient.checkFileDir(ftpPath+top_file_list[i]) == "Dir":
  156. self.treeWidget.topLevelItem(0).child(i).setText(2, _translate("MainWindow", "directory"))
  157. self.treeWidget.topLevelItem(0).child(i).setIcon(0, QIcon('../image/icon/folder.png'))
  158. self.addTreeItem(ftpclient, ftpPath + top_file_list[i], self.treeWidget.topLevelItem(0).child(i),
  159. _translate)
  160. else:
  161. self.treeWidget.topLevelItem(0).child(i).setIcon(0,QIcon('../image/icon/file.png'))
  162. self.treeWidget.topLevelItem(0).child(i).setText(2, _translate("MainWindow", "file"))
  163. print(top_file_list)
  164. def addTreeItem(self,ftpclient,filePath,parentItem,_translate):
  165. file_list = ftpclient.getdirs(filePath)
  166. for i in range(len(file_list)):
  167. parentItem.addChild(QtWidgets.QTreeWidgetItem())
  168. parentItem.child(i).setText(0, _translate("MainWindow", file_list[i]))
  169. modify_time = ftpclient.get_modify_time(filePath + "/" + file_list[i]).split(";")
  170. parentItem.child(i).setText(1, _translate("MainWindow", modify_time[2][5:-1]))
  171. parentItem.child(i).setText(3, _translate("MainWindow", modify_time[0]))
  172. if ftpclient.checkFileDir(filePath+"/"+file_list[i]) == "Dir":
  173. parentItem.child(i).setIcon(0, QIcon('../image/icon/folder.png'))
  174. parentItem.child(i).setText(2,_translate("MainWindow", "directory" ))
  175. self.addTreeItem(ftpclient, filePath +"/"+ file_list[i], parentItem.child(i),
  176. _translate)
  177. else:
  178. parentItem.child(i).setIcon(0, QIcon('../image/icon/file.png'))
  179. parentItem.child(i).setText(2, _translate("MainWindow", "file"))
  180. # 定义treewidget中item右键界面
  181. def treeWidgetItem_fun(self, pos):
  182. item = self.treeWidget.currentItem()
  183. item1 = self.treeWidget.itemAt(pos)
  184. if item != None and item1 != None: # 判断菜单是否为空
  185. popMenu = QMenu()
  186. if item.text(2)=="directory":
  187. self.upload=popMenu.addAction(QAction(u'上传', self.treeWidget))
  188. else:
  189. self.download=popMenu.addAction(QAction(u'下载', self.treeWidget))
  190. popMenu.triggered[QAction].connect(self.processtrigger) # 右键点击清空之后执行的操作
  191. popMenu.exec_(QCursor.pos()) # 执行之后菜单可以显示
  192. # 右键点击清空之后执行的操作
  193. def processtrigger(self, q):
  194. # 相应的处理
  195. command = q.text()
  196. item = self.treeWidget.currentItem()
  197. filePath=self.getLocation(item)
  198. print(filePath)
  199. if command == "上传":
  200. self.ftpOperation.ftpClient.cwd(filePath)
  201. fileUrl = QFileDialog.getOpenFileUrl(None, '打开文件', QUrl('.'),'所有文件(*.*);;Python文件(*.py);;图片(*.png *.jpg)')
  202. if fileUrl[0]!=None and isNotNull(fileUrl[0].path()):
  203. pathFile=fileUrl[0].path().strip("/")
  204. self.textBrowser.append("上传文件:"+pathFile)
  205. self.textBrowser.append("正在上传文件:" +pathFile+ " 到" + filePath)
  206. res=self.ftpOperation.upload(pathFile)
  207. self.progressDialog(5000)
  208. self.textBrowser.append("上传文件成功,文件路径:" + filePath+"/"+os.path.basename(pathFile))
  209. else:
  210. QMessageBox.information(self.MainWindow, '警告', '未选择文件!',
  211. QMessageBox.Ok | QMessageBox.Close,
  212. QMessageBox.Close)
  213. elif command == "下载":
  214. if item.parent():
  215. self.ftpOperation.ftpClient.cwd(self.getLocation(item.parent()))
  216. self.textBrowser.append("正在下载文件" + filePath)
  217. res=self.ftpOperation.download(item.text(0))
  218. self.textBrowser.append("下载文件成功,文件路径:" + res)
  219. def progressDialog(self,elapsed):
  220. dlg = QProgressDialog()
  221. dlg.setWindowTitle('等待......')
  222. dlg.setWindowModality(Qt.WindowModal)
  223. dlg.show()
  224. for val in range(elapsed):
  225. dlg.setValue(val)
  226. QCoreApplication.processEvents()
  227. if dlg.wasCanceled():
  228. break
  229. dlg.setValue(elapsed)
  230. def getLocation(self, item):
  231. path=item.text(0)
  232. print(path)
  233. if item.parent():
  234. temp = item.parent()
  235. parentPath=temp.text(0)
  236. print(path)
  237. if parentPath=='/':
  238. path=parentPath+path
  239. if temp.parent():
  240. path=self.getLocation(temp)+"/"+path
  241. return path
  242. if __name__=='__main__':
  243. import sys
  244. app = QtWidgets.QApplication(sys.argv)
  245. widget = QtWidgets.QMainWindow()
  246. ui = Ui_MainWindow()
  247. ui.setupUi(widget)
  248. widget.show()
  249. sys.exit(app.exec_())

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/255557
推荐阅读
相关标签
  

闽ICP备14008679号