c++判断ftp服务器文件存在性判断_基于Pyqt5的C/S模式客户端在线升级方案

本文介绍了如何使用C++和Pyqt5开发一个C/S模式的客户端在线升级程序。通过FTP服务器,客户端检测版本并下载更新。文章详细描述了软件打包、FTP服务器设置、客户端程序的开发流程,特别是解决下载进度显示导致的程序卡死问题,提出了异步下载和线程通信的解决方案。
摘要由CSDN通过智能技术生成

1.软件打包安装程序

利用setupfactory软件进行客户端软件打包,形成一个setup安装程序。

2. 建立FTP服务器

利用quickeasyftpserver在远程服务器中建立FTP服务器,放置2个文件,一个setup安装文件,一个是ver.txt文件,里面写上软件的版本号12位,例如20200917V001。

3. 客户端程序开发

在客户端程序中点击升级按钮后

(1) 程序首先删除本地的上一次的版本和升级文件,然后从ftp服务器上下载ver.txt,然后判断服务器的setup版本和当前软版本是否一致,不一致,就提示用户升级。

(2) 如果用户同意升级,就在ftp上下载setup安装文件。

(3) 下载完成后,再开一个线程执行setup程序,然后把当前的程序关闭,安装程序会覆盖当前的程序。

1d03cab03095defa2cc3f4ec1b62a5d7.png

运行界面1

20c2312714cd74ce4a9adc9e50b37fb3.png

运行界面2

70357a00d8b24f5f61b2fa97adcb52cd.png

提示框

问题:

这种方法比较简单,主要问题是不知道ftp文件的下载进度,会有一直卡死的现象。这个原因是进度条的定时器程序刷新UI和FTP下载程序在一个线程中,造成拥塞了。下载时就不能定时中断,刷新UI了

解决方案:

(1) 对于ftp下载采用异步方式,下载完后发送信号给主线程。

(2) 主线程点击升级按钮,绑定子线程和对应的回调函数。然后启动ftp子线程。

(3) 在回调函数中,执行此程序就是下载结束了,这时可以在主线程中启动,进度条满格,然后执行分线程执行安装程序,并在主程序中把自己结束

代码如下:

from update import Ui_MainWindowfrom PyQt5 import QtWidgetsfrom PyQt5.QtWidgets import QMessageBoximport sysimport osfrom ftplib import FTP  # 引入ftp模块import win32processfrom PyQt5.QtCore import QBasicTimer, QThread, pyqtSignalimport timemycurrent_ver = '20200916V001'  # 当前软件版本号mynew_ver = ''#异步线程class MyCal(QThread):   #自定义一个信号名    cal_signal = pyqtSignal(int)  #定义信号返回的数值类型    #构造函数    def __init__(self, mypath, filename,parent=None):     #        super(MyCal, self).__init__(parent)        self.mypath = mypath        self.filename=filename        print("分线程:",self.mypath,self.filename)    #析构函数    def __del__(self):        self.wait()    #该线程主程序    def run(self):        ##ftp下载程序版本程序        ftp = MyFtp('127.0.0.1)        ftp.login('admin', '123456')        ftp.downloadFile(self.mypath, '/down/',  self.filename)        ftp.close()        print("分线程下载结束:", self.mypath+self.filename)        self.cal_signal.emit(1)          #发射信号,传参数class MyFtp:    ftp = FTP()    def __init__(self, host, port=21):        self.ftp.connect(host, port)    def login(self, username, pwd):        self.ftp.set_debuglevel(2)  # 打开调试级别2,显示详细信息        self.ftp.login(username, pwd)        print(self.ftp.welcome)    def downloadFile(self, localpath, remotepath, filename):        os.chdir(localpath)  # 切换工作路径到下载目录        self.ftp.cwd(remotepath)  # 要登录的ftp目录        self.ftp.nlst()  # 获取目录下的文件        file_handle = open(filename, "wb").write  # 以写模式在本地打开文件        self.ftp.retrbinary('RETR %s' % os.path.basename(filename), file_handle, blocksize=1024)  # 下载ftp文件        # ftp.delete(filename)  # 删除ftp服务器上的文件    def close(self):        self.ftp.set_debuglevel(0)  # 关闭调试        self.ftp.quit()# 主窗体class MainForm(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(MainForm, self).__init__()        self.setupUi(self)        self.timer = QBasicTimer()        self.step = 0        # self.myupdate_bt()    # 进度条控制定时器    def timerEvent(self, event):        if self.step >= 100:            self.timer.stop()            self.pushButton_2.setText('开始进度条')            self.step = 0            self.progressBar.setValue(self.step)            return        self.step = self.step + 1        if self.step>=99:            self.step=99        self.progressBar.setValue(self.step)    # 进度条控制    def myprocessbar_bt(self):        pass        if self.timer.isActive():            self.timer.stop()            self.pushButton_2.setText('开始进度条')        else:            self.timer.start(100, self)            self.pushButton_2.setText('停止进度条')    def myupdate_bt(self):        pass        myhomedir = os.getcwd()        mypath = os.getcwd() + 'down'        myfilepath1 = mypath + "ver.txt"        myfilepath2 = mypath + "setup.exe"        # 删除文件        x1 = os.path.exists(myfilepath1)  # True/False        if x1 == True:            print("删除文件:" + myfilepath1)            os.remove(myfilepath1)        x1 = os.path.exists(myfilepath2)  # True/False        if x1 == True:            print("删除文件:" + myfilepath2)            os.remove(myfilepath2)        ##ftp下载程序版本程序        ftp = MyFtp('127.0.0.1)        ftp.login('admin', '123456')        ftp.downloadFile(mypath, '/down/', 'ver.txt')        ftp.close()        print("下载结束:", myfilepath1)        # 判断版本        with open(myfilepath1, 'rt') as f1:            mynew_ver = f1.readline()[0:12]            self.label_4.setText(mynew_ver)            self.label_2.setText(mycurrent_ver)        if mynew_ver != mycurrent_ver:            x1 = QMessageBox.information(self, "确认信息", "有新版本,确认是否升级", QMessageBox.Yes | QMessageBox.No)            if x1 == QMessageBox.No:                os.chdir(myhomedir)                return            print("开始升级")            QMessageBox.information(self, "确认信息", "开始下载程序!!")            self.myprocessbar_bt()#显示进度条            # self.timer.start(100, self)            ##拥塞ftp下载程序            # ftp = MyFtp('127.0.0.1')            # ftp.login('admin', '123456')            # ftp.downloadFile(mypath, '/down/', 'setup.exe')            # ftp.close()            # print("下载结束:", myfilepath2)            # QMessageBox.information(self, "确认信息", "下载程序结束!!")            ####异步FTP下载            self.cal = MyCal(mypath, 'setup.exe')  # 点击按钮后新建计算的线程            self.cal.cal_signal.connect(self.cal_callback)  # 连接计算线程的信号            self.cal.start()  # 开始运行线程        else:            QMessageBox.information(self, "确认信息", "已经是最新版本,不用升级")            os.chdir(myhomedir)            return        # 省略 使用接收到线程返回的参数        ###执行第三方程序,新线程        #win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())        os.chdir(myhomedir)        print("主程序退出")        #sys.exit()    def cal_callback(self):  # 接收到计算线程信号后的回掉函数        pass        print('异步ftp下载结束')        self.step=100        self.progressBar.setValue(self.step)        #self.myprocessbar_bt()#显示进度条        myhomedir = os.getcwd()        mypath = myhomedir        myfilepath1 = mypath + "ver.txt"        myfilepath2 = mypath + "setup.exe"        QMessageBox.information(self, "确认信息", "下载结束,开始升级")        print(myfilepath2)        win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())        sys.exit()# 主程序入口if __name__ == "__main__":    app = QtWidgets.QApplication(sys.argv)    win_main = MainForm()    win_main.show()    sys.exit(app.exec_())
界面如下
afd8f81c26151316a06cbc42583596c8.png

设计界面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值