基于Qt的网络请求和JSON解析实现软件更新检测

一、项目背景
在软件开发过程中,版本更新检测功能是非常重要的。通过实时获取服务器上的最新版本信息,软件能够及时提醒用户进行升级。这里以Qt开发框架为基础,展示了一个简单的自动更新检测功能的实现。

二、主要技术点
在本文中,我们主要探讨了几个关键的Qt技术点:

  • Qt网络模块 (QtNetwork):这个模块帮助我们实现与服务器的通信,从而获取最新版本的更新信息。
  • JSON解析模块 (QJsonDocument, QJsonObject):通过这个模块,我们可以解析从服务器获取的JSON格式数据,提取出所需的版本号和下载链接等信息。
  • QMessageBox:这个工具用于向用户展示更新提示的对话框,确保用户能够及时了解并选择是否进行更新。

三、代码实现

#ifndef XMAINWINDOW_H
#define XMAINWINDOW_H

#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDesktopServices>
#include <QFile>

QT_BEGIN_NAMESPACE
namespace Ui {
class xMainWindow;
}
QT_END_NAMESPACE

class xMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    xMainWindow(QWidget *parent = nullptr);
    ~xMainWindow();

public:
    int parseUpdateJSON(QString str);                   // 解析JSON数据
    QString getLocalVersion(const QString &filePath);   // 获取本地版本
    bool saveLocalVersionFile(const QString &jsonStr, const QString &filePath); // 保存版本文件
    void onNetworkReplyFinished(QNetworkReply *reply);  //网络数据接收

private slots:
    void on_pushButton_check_clicked();                 // button

private:
    Ui::xMainWindow *ui;

    QNetworkAccessManager *manager; // 网络请求对象
    QString m_localVersion;         // 本地版本
};
#endif // XMAINWINDOW_H

#include "xmainwindow.h"
#include "ui_xmainwindow.h"

xMainWindow::xMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::xMainWindow)
{
    ui->setupUi(this);

    manager = new QNetworkAccessManager(this);
    connect(manager, &QNetworkAccessManager::finished, this, &xMainWindow::onNetworkReplyFinished);

    // 获取本地版本号
    QString localVersionFilePath = QApplication::applicationDirPath() + "/software_update.json";
    m_localVersion = getLocalVersion(localVersionFilePath);
}

xMainWindow::~xMainWindow()
{
    delete ui;
}

int xMainWindow::parseUpdateJSON(QString str)
{
    QJsonParseError err_rpt;
    QJsonDocument root_Doc = QJsonDocument::fromJson(str.toUtf8(), &err_rpt); // 字符串格式化为JSON
    if (err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::critical(this, "检查失败", "服务器地址错误或JSON格式错误!");
        return -1;
    }

    if (root_Doc.isObject())
    {
        QJsonObject root_Obj = root_Doc.object();
        QJsonObject PulseValue = root_Obj.value("PulseVersion").toObject();
        QString Verison = PulseValue.value("LatestVerison").toString();
        QString Url = PulseValue.value("Url").toString();
        QString UpdateTime = PulseValue.value("UpdateTime").toString();
        QString ReleaseNote = PulseValue.value("ReleaseNote").toString();

        qDebug() << "Verison:" << Verison;

        if (Verison > m_localVersion)
        {
            QString warningStr = "检测到新版本!\n版本号:" + Verison + "\n更新时间:" + UpdateTime + "\n更新说明:" + ReleaseNote;
            int ret = QMessageBox::warning(this, "检查更新", warningStr, "下载更新", "跳过");
            if (ret == 0)  //点击更新
            {
                QDesktopServices::openUrl(QUrl(Url));

                // 将从服务器获取的 JSON 数据覆盖写入本地文件
                QString localVersionFilePath = QApplication::applicationDirPath() + "/software_update.json";
                if (saveLocalVersionFile(str, localVersionFilePath)) {
                    qDebug() << "本地版本文件已更新.";
                    m_localVersion = Verison;   // 更新本地版本号
                } else {
                    qWarning() << "本地版本文件更新失败.";
                }
            }
        }
        else
        {
            QMessageBox::information(this, "检查更新", "当前已经是最新版本!");
        }
    }
    return 0;
}

QString xMainWindow::getLocalVersion(const QString &filePath)
{
    // 打开文件
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "无法打开文件:" << filePath;
        return QString();  // 文件打开失败,返回空字符串
    }

    // 读取文件内容
    QByteArray fileData = file.readAll();
    file.close();

    // 解析JSON数据
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(fileData, &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "JSON解析失败:" << parseError.errorString();
        return QString();  // JSON解析失败,返回空字符串
    }

    // 确保 JSON 是对象格式
    if (!jsonDoc.isObject()) {
        qWarning() << "JSON格式错误,期望对象格式";
        return QString();  // 非对象格式,返回空字符串
    }

    // 获取 JSON 对象
    QJsonObject jsonObj = jsonDoc.object();

    // 从对象中提取 PulseVersion 对象
    if (!jsonObj.contains("PulseVersion") || !jsonObj["PulseVersion"].isObject()) {
        qWarning() << "PulseVersion 不存在或不是对象";
        return QString();
    }

    QJsonObject pulseVersionObj = jsonObj["PulseVersion"].toObject();

    // 从 PulseVersion 中提取 LatestVerison
    if (!pulseVersionObj.contains("LatestVerison") || !pulseVersionObj["LatestVerison"].isString()) {
        qWarning() << "LatestVerison 不存在或不是字符串";
        return QString();
    }

    QString latestVersion = pulseVersionObj["LatestVerison"].toString();

    //qDebug() << "localVersion:" << latestVersion;

    return latestVersion;
}

bool xMainWindow::saveLocalVersionFile(const QString &jsonStr, const QString &filePath)
{
    // 打开文件准备写入
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qWarning() << "无法打开文件写入:" << filePath;
        return false;
    }

    // 写入文件内容
    QTextStream out(&file);
    out << jsonStr;
    file.close();

    return true;
}


void xMainWindow::onNetworkReplyFinished(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NoError) {
        QString responseStr = reply->readAll(); // 获取响应数据
        parseUpdateJSON(responseStr);

    } else {
        QMessageBox::critical(this, "检查失败", "网络请求失败!");
    }
    reply->deleteLater();  // 清理reply对象
}

void xMainWindow::on_pushButton_check_clicked()
{
    QNetworkRequest quest;
    quest.setUrl(QUrl("http://192.168.9.58:8090/software_update.json")); // 设置请求的URL
    quest.setHeader(QNetworkRequest::UserAgentHeader, "RT-Thread ART");
    manager->get(quest);
}



UI设计
这个示例的UI设计非常简洁,只包含一个“检查更新”按钮。在on_pushButton_check_clicked()槽函数中,当用户点击按钮时,程序会发送网络请求来检测是否有更新。

四、功能流程
用户点击了“检查更新”按钮。
程序随即向服务器发送请求,获取最新的版本信息。
服务器返回的JSON数据被程序解析,判断是否有新版本。
如果有新版本,程序会弹出一个提示框,询问用户是否要下载更新。

五、JSON数据格式

{
    "PulseVersion": {

        "LatestVerison": "4.0.0.0",

        "UpdateTime": "2024-10-06",

		"Url": "http://192.168.9.58:8090/CheckVersion.exe",

        "ReleaseNote": "\n1.修复了启动时偶尔出现的222崩溃问题.\n2.提高了数据加载的速度,优化了性能"

    }

}

通过更新服务器上的JSON文件来控制版本,目前只更新check.exe,如果需要更新多个文件,可以自行修改parseUpdateJSON函数。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值