UI
main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>562</width><height>96</height></rect></property><property name="font"><font><family>微软雅黑</family><pointsize>10</pointsize></font></property><property name="windowTitle"><string>在线升级</string></property><widget class="QWidget" name="centralwidget"><widget class="QProgressBar" name="pbDownload"><property name="geometry"><rect><x>10</x><y>60</y><width>541</width><height>31</height></rect></property><property name="value"><number>0</number></property><property name="alignment"><set>Qt::AlignCenter</set></property><property name="textVisible"><bool>false</bool></property></widget><widget class="QLabel" name="label"><property name="geometry"><rect><x>10</x><y>10</y><width>541</width><height>41</height></rect></property><property name="font"><font><family>微软雅黑</family><pointsize>10</pointsize></font></property><property name="text"><string>在线升级中,请稍等...</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></widget></widget><resources/><connections/>
</ui>
main.py
# -*- coding: utf-8 -*-################################################################################
## Form generated from reading UI file 'main.ui'
##
## Created by: Qt User Interface Compiler version 6.6.3
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,QMetaObject, QObject, QPoint, QRect,QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,QFont, QFontDatabase, QGradient, QIcon,QImage, QKeySequence, QLinearGradient, QPainter,QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QProgressBar,QSizePolicy, QWidget)class Ui_MainWindow(object):def setupUi(self, MainWindow):if not MainWindow.objectName():MainWindow.setObjectName(u"MainWindow")MainWindow.resize(562, 96)font = QFont()font.setFamilies([u"\u5fae\u8f6f\u96c5\u9ed1"])font.setPointSize(10)MainWindow.setFont(font)self.centralwidget = QWidget(MainWindow)self.centralwidget.setObjectName(u"centralwidget")self.pbDownload = QProgressBar(self.centralwidget)self.pbDownload.setObjectName(u"pbDownload")self.pbDownload.setGeometry(QRect(10, 60, 541, 31))self.pbDownload.setValue(0)self.pbDownload.setAlignment(Qt.AlignCenter)self.pbDownload.setTextVisible(False)self.label = QLabel(self.centralwidget)self.label.setObjectName(u"label")self.label.setGeometry(QRect(10, 10, 541, 41))self.label.setFont(font)self.label.setAlignment(Qt.AlignCenter)MainWindow.setCentralWidget(self.centralwidget)self.retranslateUi(MainWindow)QMetaObject.connectSlotsByName(MainWindow)# setupUidef retranslateUi(self, MainWindow):MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"\u5728\u7ebf\u5347\u7ea7", None))self.label.setText(QCoreApplication.translate("MainWindow", u"\u5728\u7ebf\u5347\u7ea7\u4e2d,\u8bf7\u7a0d\u7b49...", None))# retranslateUi
PyDesigner
主程序
upgrade_service.py
import timeimport configparser
import requests
import sys
import threading
import psutil
import os
import zipfile
import warningsfrom PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QIcon, QMouseEvent
from ui.main import Ui_MainWindow
from qt_material import apply_stylesheet'''
pip install pyinstaller pyside6 qt_material psutil requestspyside6-uic -o ../../ui/main.py ../../ui/main.uipyinstaller --clean --icon=upgrade.ico D:\\1_local_project\IMVision\IMVDXUpgrade\\upgrade_service.py
pyinstaller upgrade_service.spec --noconfirm
'''warnings.filterwarnings('ignore', category=DeprecationWarning)class UpgradeInfo(object):def __init__(self):self.username = ''self.version = ''self.url = ''self.extra_file = 0self.extra_path = ''self.remark = ''class MainWindow(QMainWindow, Ui_MainWindow):def __init__(self):super(MainWindow, self).__init__()self.setupUi(self)self.setWindowFlags(Qt.FramelessWindowHint)# 开启鼠标追踪self.setMouseTracking(True)# 记录鼠标按下时的位置self.drag_start_position = Noneself.setWindowIcon(QIcon('icons/upgrade.ico'))self.label.setStyleSheet(self.label.styleSheet() + 'font-size: 20px;')self.upgrade_finished = Falseself.finished_chunk_size = 0self.total_file_count = 0threading.Thread(target=self.download_file).start()self.timer = QTimer(self)self.timer.timeout.connect(self.listen_download_state)self.timer.start(100)def mousePressEvent(self, event: QMouseEvent) -> None:if event.button() == Qt.LeftButton:self.drag_start_position = event.pos()def mouseMoveEvent(self, event: QMouseEvent) -> None:if self.drag_start_position is not None:delta = event.pos() - self.drag_start_positionself.move(self.pos() + delta)def mouseReleaseEvent(self, event: QMouseEvent) -> None:if event.button() == Qt.LeftButton:self.drag_start_position = Nonedef listen_download_state(self):if self.upgrade_finished:self.timer.stop()cf.set('upgrade', 'state', '0')cf.set('upgrade', 'currentVersion', new_version)cf.write(open('service.ini', 'w'))if self.total_file_count > 0:os.startfile(main_file)time.sleep(0.2)self.close()def updateLabel(self, c, t, overwrite=False):self.label.setText('正在升级...(' + c + '/' + t + ')') if not overwrite else self.label.setText(t)def download_file(self):upgrade_files = []self.finished_count = 0self.total_file_count = 0self.weight_file = 0self.extra_file = 0response = requests.get(upgrade_url + 'upgrade/v1/info?username=' + username, timeout=2)if response.status_code == 200:res = response.json()if res['code'] == 0 and res['data'] is not None:data = res['data']self.weight_file_tag = data['weight_file']self.extra_file_tag = data['extra_file']self.total_file_count = data['total_file_count']upgrade_files = (data['extra_path'].replace('[', '').replace(']', '').replace(' ', '').split(','))if self.total_file_count == 0:self.updateLabel('0', '当前已是最新版本!', True)time.sleep(1)self.upgrade_finished = Truereturnif self.weight_file_tag == 1:self.total_file_count += len(weight_files)self.updateLabel('0', str(self.total_file_count))time.sleep(0.2)# 下载主程序try:response = requests.get(upgrade_url + 'upgrade/v1/download?filename=' + main_file + '&username=' + username,stream=True)end_process(main_file)time.sleep(0.5)end_process(main_file)time.sleep(0.5)self.pbDownload.setMaximum(int(response.headers.get('Content-Length', 0)))with open(main_file_tmp, 'wb') as file:self.finished_chunk_size = 0for chunk in response.iter_content(chunk_size=8192 * 10):if chunk:file.write(chunk)self.finished_chunk_size += len(chunk)self.pbDownload.setValue(self.finished_chunk_size)QApplication.processEvents()time.sleep(0.5)# 下载完成,删除main_file,将临时文件改成main_fileos.remove(main_file)os.rename(main_file_tmp, main_file)except:# 下载失败,删除临时文件os.remove(main_file_tmp)self.updateLabel('0', '升级失败!请检查网络连接!', True)time.sleep(1)self.upgrade_finished = Truereturnself.updateLabel('1', str(self.total_file_count))time.sleep(0.2)self.finished_count = 1if self.weight_file_tag == 1:for weight_file in weight_files:weight_file_tmp = weight_file + '.tmp'try:# 下载权重文件response = requests.get(upgrade_url + 'upgrade/v1/download?filename=' + weight_file + '&username=' + username,stream=True)self.pbDownload.setMaximum(int(response.headers.get('Content-Length', 0)))with open('weights/' + weight_file_tmp, 'wb') as file:self.finished_chunk_size = 0for chunk in response.iter_content(chunk_size=8192 * 10):if chunk:file.write(chunk)self.finished_chunk_size += len(chunk)self.pbDownload.setValue(self.finished_chunk_size)QApplication.processEvents()time.sleep(0.5)# 下载完成,删除weight_file,将临时文件改成weight_fileos.remove('weights/' + weight_file)os.rename('weights/' + weight_file_tmp, 'weights/' + weight_file)self.finished_count += 1except:# 下载失败,删除临时文件os.remove('weights/' + weight_file_tmp)self.updateLabel('0', '升级失败!请检查网络连接!', True)time.sleep(1)self.upgrade_finished = Truereturnself.updateLabel(str(self.finished_count), str(self.total_file_count))# 最后下载第三方文件(zip格式)if self.extra_file_tag == 1:try:for idx, filename in enumerate(upgrade_files):response = requests.get(upgrade_url + 'upgrade/v1/download?filename=' + filename + '&username=' + username, stream=True)extra_file_zip = '_internal\\' + filenameself.pbDownload.setMaximum(int(response.headers.get('Content-Length', 0)))with open(extra_file_zip, 'wb') as file:self.finished_chunk_size = 0for chunk in response.iter_content(chunk_size=8192):if chunk:file.write(chunk)self.finished_chunk_size += len(chunk)self.pbDownload.setValue(self.finished_chunk_size)QApplication.processEvents()# 解压缩zipunzip_file(extra_file_zip, './_internal')self.updateLabel(str(idx + self.finished_count + 1), str(self.total_file_count))except:self.updateLabel('0', '升级失败!请检查网络连接!', True)time.sleep(1)self.upgrade_finished = Truereturnself.updateLabel('0', '升级完成!启动新版本...', True)time.sleep(0.5)self.upgrade_finished = Truedef close(self):super(MainWindow, self).close()def end_process(process_name):try:if is_process_running_by_name(process_name):os.system('taskkill /f /im ' + process_name)except:passdef is_process_running_by_name(process_name):for proc in psutil.process_iter(['name']):if proc.info['name'].find(process_name) == 0:return Truereturn Falsedef unzip_file(zip_path, extract_path='.'):if not os.path.exists(extract_path):os.makedirs(extract_path)with zipfile.ZipFile(zip_path, 'r') as zip_ref:zip_ref.extractall(extract_path)os.remove(zip_path)extra = {'font_family': '微软雅黑','density_scale': '0','button_shape': 'default','pyside6': True
}if __name__ == '__main__':cf = configparser.ConfigParser()cf_file = 'service.ini'if os.path.exists(cf_file):cf.read(cf_file)upgrade_url = cf.get('server', 'url')main_file = cf.get('upgrade', 'mainfile')weight_files = cf.get('upgrade', 'weightfiles').split(',')main_file_tmp = main_file + '.tmp'current_version = cf.get('upgrade', 'currentversion')new_version = cf.get('upgrade', 'newversion')state = cf.getint('upgrade', 'state')username = cf.get('sys', 'username')else:sys.exit(0)if state == 0 or (current_version == new_version):sys.exit(0)app = QApplication(sys.argv)main_window = MainWindow()apply_stylesheet(app, theme='dark_teal2.xml', extra=extra)main_window.show()sys.exit(app.exec())
配置文件 service.ini
后台服务(Java)
@ApiOperation("下载升级文件")@RequestMapping("download")public void download(@RequestParam String filename, @RequestParam String username) {UpgradeSetDO upgradeSetDO = upgradeSetMapper.selectOne(new QueryWrapper<UpgradeSetDO>().eq("username", username).eq("state", 1).last(" order by id desc limit 1"));ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();assert requestAttributes != null;HttpServletResponse response = requestAttributes.getResponse();assert response != null;String filePath = "C:\\IMVD\\UPGRADE\\" + username + "\\" + upgradeSetDO.getVersion() + "\\" + filename;File file = new File(filePath);response.setHeader("Content-Disposition", "attachment;filename=" + filename);response.setHeader("Content-Length", String.valueOf(file.length()));try (OutputStream outputStream = response.getOutputStream();BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath))) {byte[] buff = new byte[1024];int i = bis.read(buff);while (i != -1) {outputStream.write(buff, 0, buff.length);outputStream.flush();i = bis.read(buff);}} catch (IOException e) {log.error(e.getMessage());}}