1.软件打包安装程序
利用setupfactory软件进行客户端软件打包,形成一个setup安装程序 。
2. 建立FTP服务器
利用quickeasyftpserver在远程服务器中建立FTP服务器,放置2个文件,一个setup安装文件,一个是ver.txt文件,里面写上软件的版本号12位,例如20200917V001 。
3. 客户端程序开发
在客户端程序中点击升级按钮后
(1) 程序首先删除本地的上一次的版本和升级文件,然后从ftp服务器上下载ver.txt,然后判断服务器的setup版本和当前软版本是否一致,不一致,就提示用户升级 。
(2) 如果用户同意升级,就在ftp上下载setup安装文件 。
(3) 下载完成后,再开一个线程执行setup程序,然后把当前的程序关闭,安装程序会覆盖当前的程序 。

文章插图
运行界面1

文章插图
运行界面2

文章插图
提示框
【基于Pyqt5的C/S模式客户端在线升级方案】问题:
这种方法比较简单,主要问题是不知道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 = mypathself.filename=filenameprint("分线程:",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 = 0self.progressBar.setValue(self.step)returnself.step = self.step + 1if self.step>=99:self.step=99self.progressBar.setValue(self.step)# 进度条控制def myprocessbar_bt(self):passif self.timer.isActive():self.timer.stop()self.pushButton_2.setText('开始进度条')else:self.timer.start(100, self)self.pushButton_2.setText('停止进度条')def myupdate_bt(self):passmyhomedir = os.getcwd()mypath = os.getcwd() + '\down\'myfilepath1 = mypath + "ver.txt"myfilepath2 = mypath + "setup.exe"# 删除文件x1 = os.path.exists(myfilepath1)# True/Falseif x1 == True:print("删除文件:" + myfilepath1)os.remove(myfilepath1)x1 = os.path.exists(myfilepath2)# True/Falseif 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)returnprint("开始升级")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):# 接收到计算线程信号后的回掉函数passprint('异步ftp下载结束')self.step=100self.progressBar.setValue(self.step)#self.myprocessbar_bt()#显示进度条myhomedir = os.getcwd()mypath = myhomedirmyfilepath1 = 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_())
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 荷叶茶的副作用是什么,冬瓜荷叶茶的副作用
- 一篇短文介绍 Defer 是如何工作的
- 黄颜色的茶叶是什么茶,东方尤物茶的特点是什么
- 哈尼族的煎茶习俗,哈尼族的土锅茶文化
- 全网最全的IDEA热部署方案,看完弄懂,再也不用加班
- 后期辛辛苦苦修好的图片,别在看似简单的最后输出时搞砸了
- 你想要的功能,Edge浏览器都有
- Python接口自动化测试的实现
- 只做技术的程序员后来都怎么样了?值得深思
- 无服务器技术如何实现最佳的DevOps实践
