使用QNetworkRequest,实现网络连接

2023-11-09

首先要在头文件中包含以下文件

#include<QNetworkRequest>
#include<QNetworkReply>
#include<QNetworkAccessManager>

post请求的写法

/**
    * @brief Postt请求
    * @param (不可为空)strUrl 输入参数,请求的Url地址,如:http://192.168.0.255/login  根据需要在后面拼接相应的内容,传递变量
    * @param (可为空)strFiles json 格式字符串,用于上传文件,表单数据,json格式的表单值,
    *       {
            "file1":                        注意表示路径要用 '/',key中应含有"file",单个文件或多个文件都用数组格式
                [
                "C:/user/project/test1.txt", 
                "C:/user/project/test2.txt"
                ]              
            "form1":"f1",
            "user":{
                    "id":1,
                    "loginName":"loginName1",
                    "userName","userName1"
                    }
            } !记得转成QString类型传入
    * @param (可为空)strPost 登陆时,用于传json格式body,"{\"loginName\":\"zhangsan\",\"password\":\"123456\",\"machineCode\":\"machineCodeX64\"}"
    *                传值时,用于传json格式header,"{\"header1\":\"h1\",\"header2\":\"h2\"}"
    * @param  (建议传空变量)strResponse 输出参数,返回的内容
    * @return 返回是否Post成功
    */
    CHTTPCLIENT_EXPORT int doPost(QString& strUrl, const QString& strFiles, const QString& strPost, QString& strResponse);
int CHttpClient::doPost(QString& strUrl, const QString& strfiles, const QString& strPost, QString& strResponse)
{
    std::tuple<QString, QString> FUrl = ^^^^^^^^;//通过读取本地配置文件获得端口号和主机号
    QString Url = QString("http://%1:%2/%3").arg(std::get<0>(FUrl)).arg(std::get<1>(FUrl)).arg(strUrl);
    QTimer timer;										// 计时,一是不让程序在请求完成前就退出,另一方面是控制请求时间,判断超时就退出
    timer.setInterval(1500);                                // 设置超时时间 1.5 秒
    timer.setSingleShot(true);                              // 单次触发
    QNetworkAccessManager* g_manager = new QNetworkAccessManager();            // 初始化
    QNetworkRequest request;
    request.setUrl(QUrl(Url));							// 设置请求地址
    request.setRawHeader("Datagrid-Authorization:", Token.toUtf8());//token,是用户登陆时获得的,之后的请求都要先设置token
    QNetworkReply* reply = nullptr;						// 初始化请求的返回类
    if (strfiles.isEmpty()) {
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");//设置请求头
        QJsonDocument strPost_doc = QJsonDocument::fromJson(strPost.toUtf8());
        QByteArray dataArray = strPost_doc.toJson(QJsonDocument::Compact);
        reply = g_manager->post(request, dataArray);     // 发出post请求
    }
    else {
        QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
        QJsonParseError JSON_Error;
        QJsonDocument doc = QJsonDocument::fromJson(strfiles.toUtf8(), &JSON_Error);
        if (doc.isEmpty() || (JSON_Error.error != QJsonParseError::NoError)) {
            return 0;
        }
        //JSON对象
        QVariantMap jsonMap = doc.toVariant().toMap();	
        QMap<QString, QVariant> paths;					// 存上传文件的路径
        QMap<QString, QVariant> params{};				// 存其他要请求的数据
        for (auto it = jsonMap.constBegin(); it != jsonMap.constEnd(); ++it) {
            if (it.key().contains("file")) {
                paths.insert(it.key(), it.value());
            }
            else if (it.key().contains("form")) {
                params.insert(it.key(), it.value().toString().toUtf8());
            }
            else {
                auto _valuetype = it.value().type();
                if (!it.value().toJsonObject().isEmpty()) {
                    auto _value = it.value().toJsonObject();
                    QJsonDocument json_doc(_value);
                    params.insert(it.key(), QString(json_doc.toJson()).remove(QRegExp("\\s")).toUtf8());
                }
                else if (!it.value().toString().isEmpty()) {
                    auto _value = it.value().toString();
                    params.insert(it.key(), _value.toUtf8());
                }
                else if (it.value().toInt() != 0) {
                    auto _value = it.value().toInt();
                    params.insert(it.key(), QString(_value).toUtf8());
                }
                else if (!it.value().toStringList().isEmpty()) {
                    auto _value = it.value().toStringList().join(",").toUtf8();
                    params.insert(it.key(), _value);
                }
            }
        }
        QJsonDocument jsonDocument = QJsonDocument::fromJson(strPost.toUtf8().data());
        if (!jsonDocument.isNull()) {//判断是否为空
            QJsonObject* json_obj = new QJsonObject(jsonDocument.object());
            for (auto it = json_obj->begin(); it != json_obj->end(); ++it) {
                request.setRawHeader(it.key().toUtf8(), it.value().toString().toUtf8());
            }
        }

        for (auto it = params.cbegin(); it != params.cend(); ++it) {
            QString name = it.key();
            auto value = it.value().toByteArray();
            QHttpPart textPart;
            if (name.contains("form")) {
                textPart.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(name));
            }
            else {
                textPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=utf-8"));
                textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(name));
            }
            textPart.setBody(value);
            multiPart->append(textPart);
        }
        if (paths.size() > 0) {
            for (auto it = paths.constBegin(); it != paths.constEnd(); ++it) {
                QString inputName = it.key();
                auto filelist = it.value().toList();
                for (int i = 0; i < filelist.size(); ++i)
                {
                    QString _file = filelist.at(i).toString();
                    QFile* file = new QFile(_file, multiPart);
                    QFileInfo file_info(_file);
                    if (!file->open(QIODevice::ReadOnly)) {
                        QString failMessage = QString("打开文件失败[%2]: %1").arg(_file).arg(file->errorString());
                        multiPart->deleteLater();
                        return 0;
                    }
                    auto x = file_info.fileName();
                    QString disposition = QString("form-data; name=\"%1\"; filename=\"%2\"").arg(inputName).arg(file_info.fileName());
                    QHttpPart filePart;
                    filePart.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
                    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(disposition));
                    filePart.setBodyDevice(file);
                    multiPart->append(filePart);
                }
            }
        }

        reply = g_manager->post(request, multiPart);
        multiPart->setParent(reply);
    }
    if (nullptr == reply)return 0;
    QEventLoop loop;                                                    // 开启循环等待
    QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);        // 超时则退出循环
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); // 请求成功则退出循环
    timer.start();                                                      // 开始计时
    loop.exec();                                                        // 启动事件循环
    if (timer.isActive()) {                                             // 处理响应
        timer.stop();
        if (reply->error() != QNetworkReply::NoError) {                 // 错误处理
            qDebug() << "Error String : " << reply->errorString();
        }
        else {
            QVariant variant = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
            int nStatusCode = variant.toInt();
            QByteArray bytes = reply->readAll();                        // 处理请求到的数据
            QJsonParseError jsonError;
            QJsonDocument jsDoc = QJsonDocument::fromJson(bytes, &jsonError);
            if (jsonError.error != QJsonParseError::NoError) {
                qDebug() << QStringLiteral("解析Json失败");
                return 0;
            }
            strResponse = QString(jsDoc.toJson(QJsonDocument::Indented));   // 把请求结果回传
        }
    }
    else {                                                              // 处理超时
        QObject::disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "Timeout";
    }
    return 1;
}

get请求示例

 /**
   * @brief Get请求
   * @param (不可为空)strUrl 输入参数,请求的Url地址,如:http://192.168.0.3/security/manager/user/test/get/simplest
   * @param (不下载文件时可以传空值)strSavePath 下载文件的保存地址,如:下载图片格式文件strSavePath = "C:/Users/Administrator/Pictures/pic.png",请求文件类型要和提供的保存格式一致,否则会导致乱码
   * @param (建议传空变量)strResponse 输出参数,返回的内容
   * @return 返回是否Get成功
   */
    CHTTPCLIENT_EXPORT int doGet(QString& strUrl, const QString& strSavePath, QString& strResponse);
int CHttpClient::doGet(QString& strUrl, const QString& strSavePath, QString& strResponse)
{
    std::tuple<QString, QString> FUrl = ^^^^^^^^;//获得端口号和主机号
    QString Url = QString("http://%1:%2/%3").arg(std::get<0>(FUrl)).arg(std::get<1>(FUrl)).arg(strUrl);
    qDebug() << Url;
    QTimer timer;
    timer.setInterval(15000);                                // 设置超时时间 1.5 秒
    timer.setSingleShot(true);                              // 单次触发
    QNetworkRequest request;
    QNetworkReply* reply = nullptr;
    request.setUrl(QUrl(Url));
    request.setRawHeader("Datagrid-Authorization:", g_Token.toUtf8());
    QNetworkAccessManager* g_manager = new QNetworkAccessManager();
    if (strSavePath.isEmpty()) {
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    }
    reply = g_manager->get(request);
    QEventLoop loop;                                                    // 开启循环等待
    QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);        // 超时则退出循环
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); // 请求成功则退出循环
    timer.start();                                                      // 开始计时
    loop.exec();                                                        // 启动事件循环
    if (timer.isActive()) {                                             // 处理响应
        timer.stop();
        if (reply->error() != QNetworkReply::NoError) {                 // 错误处理
            qDebug() << "Error String : " << reply->errorString();
        }
        else {
            QVariant variant = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
            int nStatusCode = variant.toInt();
            QByteArray bytes = reply->readAll();                        // 处理请求到的数据
            QJsonParseError jsonError;
            QJsonDocument jsDoc = QJsonDocument::fromJson(bytes, &jsonError);
            if (jsonError.error != QJsonParseError::NoError) {
                qDebug() << QStringLiteral("解析Json失败");
                if (!strSavePath.isEmpty()) {
                    QFile* file = new QFile(strSavePath);
                    // [1] 打开下载文件,如果打开文件出错,不进行下载
                    if (!file->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
                        file->close();
                        file->deleteLater();
                        qDebug().noquote() << QString("[错误] 打开文件出错: %1").arg(strSavePath);
                        return 0;
                    }
                    file->write(bytes);
                    file->flush();          //不关闭文件,文件内容将为空
                    file->close();
                    file->deleteLater();
                }
            }
            else {
                strResponse = QString(jsDoc.toJson(QJsonDocument::Indented));   // 把请求结果回传
            }
        }
    }
    else {                                                              // 处理超时
        QObject::disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "getTimeout";
    }
    return 1;
}

使用get下载文件

bool doDownLoad(const QString& strUrl, const QString& strSavePath)
{
    bool isSuccess = true;
    QFile* tempFile;
    QTimer timer;
    QNetworkRequest request;
    QNetworkReply* reply = nullptr;
    request.setUrl(QUrl(strUrl));
    request.setRawHeader("Datagrid-Authorization", g_Token.toUtf8());
    QNetworkAccessManager* g_manager = new QNetworkAccessManager();
    reply = g_manager->get(request);

    QEventLoop loop;                                                                // 开启循环等待
    QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);           // 超时则退出循环
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);    // 请求成功则退出循环
    QObject::connect(reply, &QNetworkReply::finished, [&]() {
        if (reply->error() != QNetworkReply::NoError) {                             // 错误处理
            qDebug() << "Error String : " << reply->errorString() << strUrl ;
            emit errorBox("资源下载错误:"+ reply->errorString());
            isSuccess = false;
        }
        });
    QObject::connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(slotDownLoadSpeed(qint64, qint64))); // 请求成功则退出循环
    QObject::connect(reply, &QNetworkReply::readyRead, [&]() {
        QByteArray bytes = reply->readAll();
        tempFile->write(bytes);
        tempFile->flush();
        });
    if (!strSavePath.isEmpty()) {
        tempFile = new QFile(strSavePath);
        // [1] 打开下载文件,如果打开文件出错,不进行下载
        if (!tempFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            tempFile->close();
            tempFile->deleteLater();
            qDebug().noquote() << QString("[错误] 打开文件出错: %1").arg(strSavePath);
            emit errorBox("资源下载路径错误:"+ strSavePath);
            isSuccess = false;
        }
    }
    loop.exec();                                                                    // 启动事件循环
    tempFile->close();
    tempFile->deleteLater();
    return isSuccess;
}

剩余的put,和delete请求,套用上面两个请求即可

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用QNetworkRequest,实现网络连接 的相关文章

  • 通过 VLA 数组跳转到 goto 时出现分段错误

    以下示例演示了该问题 include
  • ZedGraph 缩放和调整大小

    当我绘制图形 放大和缩小并重新绘制图形时 图形的位置不会改变 我想要做的是 每当重新绘制数据时 视图都会更改以查看所有图形数据 如果您在重绘之前放大或缩小 这似乎会被禁用 Thanks 设置属性 IsZoomOnMouseCenter对于控
  • 将内核链接到 PTX 函数

    我可以使用 PTX 文件中包含的 PTX 函数作为外部设备函数 将其链接到另一个应调用该函数的 cu 文件吗 这是另一个问题CUDA 将内核链接在一起 https stackoverflow com questions 20636800 c
  • 如何获取任意类型的默认值

    在 C 中我可以写这样的东西 class AnyThing
  • 使用 boost::iterator_facade<>

    我有一个链表结构 struct SomeLinkedList const char bar int lots of interesting stuff in here DWORD foo SomeLinkedList pNext 它是现有
  • 设置外部应用程序焦点

    在 VB NET 中 您可以使用以下命令将焦点设置到外部应用程序 AppActivate Windows Name or AppActivate processID As Integer 现在 如果您这样做 则效果很好 Dim intNot
  • F# 内联如何工作?

    对于 F 我的理解是您可以使用 inline 关键字在调用站点执行类型专门化 那是 val inline a gt b gt c when a or b static member a b gt c 约束条件是 a or b必须有一个静态成
  • 为什么Boost在“程序选项”中使用全局函数覆盖来实现自定义验证器

    这个例子 http www boost org doc libs 1 55 0 doc html program options howto html idp163429032显示一个名为validate在全局范围内定义重载函数boost
  • 让 GCC/Clang 使用 CMOV

    我有一个简单的标记值联合 这些值可以是int64 ts or doubles 我正在对这些联合进行加法 但需要注意的是 如果两个参数都代表int64 t值 那么结果也应该有一个int64 t value 这是代码 include
  • 编译器在函数名称前添加下划线前缀的原因是什么?

    当我看到 C 应用程序的汇编代码时 如下所示 emacs hello c clang S O hello c o hello s cat hello s 函数名称以下划线作为前缀 例如callq printf 为什么这样做以及它有什么优点
  • 在标准库中静态链接时如何支持动态插件?

    假设一个应用程序myapp exe是使用构建的g 它使用标志 static libstdc 这样就可以安装在没有环境的情况下libstdc so myapp exe还添加了对某些功能的插件支持plugf可以通过动态加载dlopen来自共享库
  • C# Linq 可以做组合数学吗?

    我有这个数据结构 class Product public string Name get set public int Count get set var list new List
  • DLL 中的 XP 风格组合框

    我需要使用 C 和 WIN32 API 无 MFC 在 DLL 中创建 XP 风格的组合框 我设法在 DLL 中创建控件 不是以 XP 风格 我设法在带有清单的 exe 中创建 XP 样式组合框 但它在 DLL 中不起作用 为了让您的 DL
  • 一个对大文件有效的轻量级 XML 解析器?

    我需要解析潜在的巨大 XML 文件 所以我猜这排除了 DOM 解析器 是否有任何优秀的 C 轻量级 SAX 解析器 在占用空间上可与 TinyXML 相媲美 XML的结构非常简单 不需要诸如命名空间和DTD之类的高级东西 只是元素 属性和
  • C语言中如何将整数转换为字符? [复制]

    这个问题在这里已经有答案了 C语言中如何将整数转换为字符 C 中的字符已经是数字 字符的 ASCII 代码 无需转换 如果要将数字转换为相应的字符 只需添加 0 即可 c i 0 0 是 ASCii 表中的一个字符
  • RabbitMQ + Windows + LDAP 无需发送密码

    我正在尝试在 Windows 7 上使用 RabbitMQ 3 6 2 进行 LDAP 身份验证 授权 我已经在应用程序发送用户名 密码的情况下进行了基本身份验证 但密码位于我需要弄清楚如何进行的代码中避免 有没有人在不提供密码的情况下成功
  • Azure Function App Azure 服务总线触发器触发两次

    我使用带有服务总线触发器的 Azure Function Apps 来读取服务总线并对服务总线消息的内容执行操作 服务总线接收 JSON 序列化对象 然后将 JSON 消息反序列化回 Function App 中的对象 然而 由于某种原因
  • 没有运算符“<<”与这些操作数匹配[重复]

    这个问题在这里已经有答案了 不知道发生了什么事 我查看了与此问题类似的其他帖子 但到目前为止没有解决方案有帮助 这是带有错误部分注释的代码 在某一时刻 它说 不起作用 而在代码的其余部分中 它说 include
  • 通过 OCI 调用 Oracle 存储过程并使用 C++ 中的 out ref 游标返回结果

    我想使用 OCI 接口从 C 调用 Oracle 存储过程 并使用 out SYS REF CURSOR 作为过程的参数来迭代结果 我是 OCI 新手 所以可能会遗漏一些简单的东西 大部分代码取自这里 我的存储过程是 CREATE OR R
  • “保留供任何使用”是什么意思?

    注意 这是一个c questions tagged c问题 虽然我补充说c questions tagged c 2b 2b如果某些 C 专家可以提供 C 使用与 C 不同的措辞的基本原理或历史原因 在 C 标准库规范中 我们有这个规范文本

随机推荐