Qt - Qt中HTTP相关的类

前言

本篇文章来给大家讲解QT中的Http协议,Http协议主要用于网络中数据的请求和响应,那么这篇文章将给大家讲解一下这个协议。

1、HTTP协议概述

HTTP(超文本传输协议)是互联网上应用最为广泛的协议之一,它定义了客户端和服务器之间进行通信的规则。HTTP是一种无状态的协议,它通过请求-响应模型来实现客户端和服务器之间的数据传输。
以下是HTTP的一般工作流程:

1.客户端发送HTTP请求:客户端(通常是Web浏览器)向服务器发送HTTP请求。请求由以下部分组成:

请求方法(GET、POST、PUT、DELETE等):指定服务器执行的操作类型。
资源路径:指定要访问的服务器上的资源路径。
请求头:包含有关请求的其他元数据,如请求的主机、内容类型等。
请求正文(对于某些请求方法):包含请求所携带的数据。

2.服务器处理请求:服务器接收并解析HTTP请求,执行相应的操作:

检查请求的合法性和安全性。
处理请求中指定的资源或执行请求中指定的操作。
构造HTTP响应。

3.服务器发送HTTP响应:服务器生成HTTP响应,响应由以下部分组成:

状态码:指示请求是否成功或出现错误的数字代码。
响应头:包含有关响应的元数据,如响应的内容类型、长度等。
响应正文:包含服务器返回给客户端的实际数据。

4.客户端接收HTTP响应:客户端接收并解析HTTP响应:

检查响应的状态码以确定请求的成功与否。
解析响应头以获取响应的元数据。
处理响应正文中的数据。

HTTP使用TCP协议作为传输协议,默认使用80端口进行通信。它是一种无连接协议,这意味着每个请求都是独立的,服务器不会保留先前请求的状态信息。为了在请求之间保持状态,可以使用Cookie或会话等机制。
此外,HTTP还支持各种请求方法,最常见的是GET和POST。GET方法用于从服务器获取资源,而POST方法用于向服务器提交数据。
总结起来,HTTP是一种用于在客户端和服务器之间传输数据的协议。它为Web应用程序提供了通信和数据交换的基础,是实现互联网应用的核心之一

2、HTTP的两种模型

1.B/S模型

B/S模型是一种基于浏览器和服务器的交互模型,通常用于Web应用程序。在这种模型中,客户端使用浏览器作为前端界面,通过HTTP协议与服务器进行通信。客户端(浏览器)负责显示用户界面,发送HTTP请求,并接收和渲染服务器返回的HTML、CSS和JavaScript等资源。服务器负责存储数据、处理业务逻辑和生成动态网页内容。B/S模型具有以下特点:

客户端只需安装浏览器,无需安装额外客户端软件。
应用程序部署在服务器上,用户通过浏览器访问。
跨平台性好,可以在不同操作系统和设备上使用。

2.C/S模型

C/S模型是一种基于客户端和服务器的交互模型,常用于传统的桌面应用程序。在这种模型中,客户端通过安装在本地计算机上的客户端软件与服务器进行通信。客户端负责处理用户界面和部分业务逻辑,发送请求到服务器并接收响应。服务器负责处理业务逻辑和存储数据。C/S模型具有以下特点:

需要在客户端安装相应的客户端软件,适用于特定平台和操作系统。
应用程序的逻辑部分可以在客户端执行,减轻服务器的负担。
可以通过局域网或互联网与服务器进行通信。
可以实现一些功能更复杂、操作更强大的应用程序。

 

3、HTTP请求报文

请求报文是由客户端发送给服务器,用于请求特定资源或执行特定操作。它由以下几个部分组成:
请求行:描述了请求的方法、目标资源的路径和HTTP协议的版本,通常包含以下三个字段:

请求方法:指定了客户端希望服务器执行的操作,如GET、POST、PUT、DELETE等。
请求目标:表示客户端希望访问的资源路径,可以是绝对路径或相对路径。
协议版本:指定所使用的HTTP协议的版本,如HTTP/1.1。
请求头:包含了关于请求的附加信息,格式为键值对。常见的请求头字段包括:

Host:指定请求的目标主机。
User-Agent:标识发送请求的客户端应用程序。
Content-Type:指定请求正文的类型。
请求正文(可选):包含客户端发送给服务器的数据,通常在使用POST等方法时使用。

 

4、HTTP响应报文

响应报文是服务器对客户端请求的回应,包含了所请求资源的数据或执行结果。它由以下几个部分组成:
状态行:描述了响应的状态,包含以下三个字段:

协议版本:指定所使用的HTTP协议的版本,如HTTP/1.1。
状态码:表示服务器对请求的处理结果,如200表示成功,404表示资源未找到。
状态信息:对状态码进行简短的解释说明。
响应头:包含了关于响应的附加信息,格式为键值对。常见的响应头字段包括:

Content-Type:指定响应正文的类型。
Content-Length:指定响应正文的长度。
Set-Cookie:在响应中设置Cookie。
响应正文:包含了服务器返回给客户端的数据,可以是HTML、JSON、文件等。

 

 

5、调试软件Postman

Postman是一款广泛使用的API开发和测试工具,它提供了一个强大的图形用户界面(GUI),用于发送HTTP请求、测试和调试API。

安装非常简单最近在百度查找进行下一步安装即可:

在postman软件中可以请求到JSON格式的数据:

6、QT中的HTTP类

Qt中处理HTTP请求和响应相关的类

类名 主要功能
QNetworkAccessManager 用于发送HTTP请求和接收响应的类。
QNetworkRequest     表示HTTP请求的类,可以设置请求URL、请求头等信息。
QNetworkReply     表示HTTP响应的类,可以读取响应的内容、错误处理等。
QNetworkCookieJar  用于管理HTTP请求和响应中的Cookie类。
QNetworkCookie     表示HTTP请求和响应中的Cookie的类。
QNetworkProxy     表示网络代理的类,可以设置代理服务器来处理HTTP请求和响应。

 

在Qt中,用于进行HTTP通信的类是QNetworkAccessManager类和相关的类。QNetworkAccessManager提供了一个用于发送网络请求和接收网络响应的高层API,它基于Qt的网络模块实现。

以下是一些与HTTP通信相关的类和其主要功能:

QNetworkAccessManager类:

该类用于发送HTTP请求和接收HTTP响应。
可以发起GET、POST、PUT、DELETE等各种类型的请求。
提供了信号和槽机制,允许处理请求的完成、错误和响应等事件。
支持同步和异步方式发送请求。

QNetworkRequest类:

表示一个HTTP请求。
可以设置请求的URL、请求头、请求方法等属性。
可以添加自定义的请求头字段。

QNetworkReply类:

表示一个HTTP响应。
提供了获取响应状态码、响应头、响应正文等信息的方法。
可以通过该类获取服务器返回的数据。

QNetworkCookieJar类:

用于管理和存储HTTP请求和响应中的Cookie。
可以设置和获取Cookie,并将其与请求关联起来。
这些类的组合使用可以实现在Qt应用程序中进行HTTP通信的功能。以下是一个简单的示例代码,演示如何使用QNetworkAccessManager发送GET请求并处理响应:

 

7、使用HTTP类请求数据

使用HTTP类请求数据步骤:

1.使用QNetworkAccessManager类创建网络访问管理器

2.使用QNetworkRequest创建请求对象

3.使用QNetworkReply发出GET请求(在请求完成后一定要记得使用deleteLater来清理释放资源)

4.连接信号与槽得到数据

示例1:

此方式使用了 Lambda 表达式连接信号与槽

#include <QCoreApplication>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建网络访问管理器
    QNetworkAccessManager m_manger;

    // 创建请求对象
    QNetworkRequest request;
    QUrl url("http://www.baidu.com");
    request.setUrl(url);

    // 发出GET请求
    QNetworkReply* reply = m_manger.get(request);

    // 连接请求完成的信号
    QObject::connect(reply, &QNetworkReply::finished, [&]() {
        // 读取响应数据
        QByteArray responseData = reply->readAll();
        qDebug() << responseData;

        // 请求完成后,清理资源
        reply->deleteLater();
        qApp->quit();
    });

    return a.exec();
}

代码改进版本:

此方式就是槽函数单独分开写了,原理与上面一样的。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

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

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void handleNetworkResponse();

private:
    Ui::Widget *ui;

    // 创建网络访问管理器
    QNetworkAccessManager m_manger;
    QNetworkReply* m_reply;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

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

    // 创建请求对象
    QNetworkRequest request;
    QUrl url("https://www.leawo.org/images/7days_prom_en.jpg");
    request.setUrl(url);

    // 发出GET请求
    m_reply = m_manger.get(request);

    // 连接请求完成的信号
    QObject::connect(m_reply, &QNetworkReply::finished, this, &Widget::handleNetworkResponse);
}

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

void Widget::handleNetworkResponse()
{
    // 读取响应数据
    QByteArray responseData = m_reply->readAll();
    qDebug() <<"responseData = " <<responseData;

    // 请求完成后,清理资源
    m_reply->deleteLater();
}

运行结果:

 

示例2:

widget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

// QT += network
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QHttpPart>
#include <QHttpMultiPart>
#include <QFile>

#include <QTimer>

namespace Ui {
class MainWidget;
}

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MainWidget(QWidget *parent = nullptr);
    ~MainWidget();

    //get请求测试
    void getTest();
    //post请求测试
    void postTest();
    //表单测试
    void formTest();

public slots:
    //获取异步结果
    void receiveReply(QNetworkReply *reply);

private:
    Ui::MainWidget *ui;

    QNetworkAccessManager *manager;
    QTimer timer;
};

#endif // MAINWIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QUrlQuery>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>

#include <QDebug>

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

    manager=new QNetworkAccessManager(this);

    //查看支持的协议
    qDebug()<<manager->supportedSchemes();
    //安装了openssl,会有https
    //("ftp", "file", "qrc", "http", "data")

    //QNetworkAccessManager是异步的
    connect(manager, &QNetworkAccessManager::finished, this, &MainWidget::receiveReply);

    //测试get
    connect(ui->btnGet,&QPushButton::clicked,this,&MainWidget::getTest);
    //测试post
    connect(ui->btnPost,&QPushButton::clicked,this,&MainWidget::postTest);
    //测试form
    connect(ui->btnForm,&QPushButton::clicked,this,&MainWidget::formTest);


    //定时器拿来验证是否阻塞界面
    connect(&timer,&QTimer::timeout,this,[this]()
    {
        ui->editTime->setTime(QTime::currentTime());
    });
    timer.start(1000); //定时1s
}

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

void MainWidget::getTest()
{
    //构建请求对象
    QNetworkRequest request;
    request.setUrl(QUrl(ui->editGetUrl->text()));

    //设置请求头
    //已知头类型参见文档QNetworkRequest::KnownHeaders
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
    //自定义类型
    request.setRawHeader("self-header","gongjianbo");

    //发送请求
    manager->get(request);

    //同步处理,可以开启一个局部的事件循环,等待响应,不会阻塞线程
    //QNetworkReply *reply=manager->get(request);
    //QEventLoop eventLoop;
    //connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
    //eventLoop.exec();
    //receiveReply(reply);

    //超时处理,可以使用定时器调用abort、close来终止当前的请求
    //QNetworkReply *reply=manager->get(request);
    //if(reply->isRunning()){
    //    QTimer *timer=new QTimer(reply);//对象树关联释放,也可以在finish进行释放
    //    timer->setSingleShot(true);
    //    //超时就结束
    //    connect(timer,&QTimer::timeout,reply,&QNetworkReply::abort);
    //    //结束就关定时器
    //    connect(reply,&QNetworkReply::finished,timer,&QTimer::stop);
    //    //定时
    //    timer->start(5000);
    //}
}

void MainWidget::postTest()
{
    //构建请求对象
    QNetworkRequest request;
    request.setUrl(QUrl(ui->editPostUrl->text()));

    //设置请求头
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");

    //发送请求
    manager->post(request,ui->editPostData->toPlainText().toUtf8());
}

void MainWidget::formTest()
{
    QNetworkAccessManager manager2;
    //构建一个multiPart用于提交表单
    //注意,multiPart请在请求完成后再删除
    QHttpMultiPart *multiPart=new QHttpMultiPart(QHttpMultiPart::FormDataType);

    //文本内容
    QHttpPart namePart;
    //Content-Type对照表详情百度http://tool.oschina.net/commons/
    namePart.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/plain"));
    namePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"thename\";"));
    namePart.setBody("gongjianbo");
    QHttpPart agePart;
    agePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"theage\";"));
    agePart.setBody("27");
    multiPart->append(namePart);
    multiPart->append(agePart);

    //文件内容
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); //我用application传各种类型文件
    //示例里没有filename,导致提交不成功
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"thefile\";filename=\"file.txt\";"));
    QFile *textFile = new QFile(":/file.txt");
    textFile->setParent(multiPart); //在删除reply时一并释放
    if(textFile->open(QIODevice::ReadOnly)){
        //要读取小块数据,请使用setBody(); 对于像图像这样的较大数据块,请使用setBodyDevice()。
        filePart.setBodyDevice(textFile);
        multiPart->append(filePart);
    }

    //图片内容
    QHttpPart imagePart;
    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
    //示例里没有filename,导致提交不成功
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"theimage\";filename=\"image.png\";"));
    QFile *imageFile = new QFile(":/image.png");
    imageFile->setParent(multiPart); //在删除reply时一并释放
    if(imageFile->open(QIODevice::ReadOnly)){
        imagePart.setBodyDevice(imageFile);
        multiPart->append(imagePart);
    }

    //在我们公司里使用的时候,没有Boundary也会导致提交不成功
    multiPart->setBoundary("qtdata");
    QNetworkRequest request(QUrl("http://httpbin.org/post"));
    request.setRawHeader("Content-Type","multipart/form-data;boundary=qtdata");

    //提交表单
    QNetworkReply *reply=manager2.post(request,multiPart);
    multiPart->setParent(reply); //在删除reply时一并释放

    QEventLoop eventLoop;
    connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
    eventLoop.exec();

    qDebug()<<"reply:"<<reply->readAll();
    reply->deleteLater();
}

void MainWidget::receiveReply(QNetworkReply *reply)
{
    //请求方式get、post等,对应QNetworkAccessManager的Operation枚举
    //对于restful接口需要判断此枚举
    qDebug()<<"operation:"<<reply->operation();
    //路径
    qDebug()<<"url:"<<reply->url();
    //状态码
    const int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"status code:"<<status_code;
    //主动调用QNetworkReply的close或者abort也会触发finished,这时状态码为0
    //访问失败状态码也会为0
    if(status_code == 0 && reply->errorString() == "Operation canceled")
    {
        qDebug()<<"timeout";
    }

    if(reply->error() != QNetworkReply::NoError)
    {
        //处理中的错误信息
        qDebug()<<"reply error:"<<reply->errorString();
    }
    else
    {
        //重定向
        if (status_code == 301 || status_code == 302){
              // Or the target URL if it was a redirect:
              QVariant redirectionTargetUrl =reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
              qDebug() << "redirection Url is " << redirectionTargetUrl.toString();
              QUrl url(redirectionTargetUrl.toString());
              manager->get(QNetworkRequest(url));
        }

        //获取响应信息并展示到ui,这里没有解析
        const QByteArray reply_data = reply->readAll();
        //qDebug()<<"read all:"<<reply_data;
        ui->editRecv->append("[Reply] "+QTime::currentTime().toString("hh:mm:ss"));
        //根据自己的编码选用对应的QString方法
        ui->editRecv->append(QString::fromUtf8(reply_data));

        //解析json
        /*QJsonParseError json_error;
        QJsonDocument document=QJsonDocument::fromJson(reply_data, &json_error);
        if (json_error.error==QJsonParseError::NoError) {
            if(document.isObject()){
                const QJsonObject obj=document.object();
                qDebug()<<obj;
                if(obj.contains("args")){
                    QJsonValue value=obj.value("args");
                    qDebug()<<value;
                    //QJsonValue(object, QJsonObject({"ie":"utf-8"}))
                }
            }
        }else{
            qDebug()<<"json error:"<<json_error.errorString();
        }*/
    }
    reply->deleteLater();
}

widget.ui

运行结果:

注:Qt默认是无法对https网站进行请求的,用请求http的方式下载https网站没有数据,在pro文件中添加 Qt += network,在初始程序中加入

 QNetworkAccessManager *manager = new QNetworkAccessManager(this);
 qDebug() << manager->supportedSchemes();

运行后会在输出界面显示

 没有https说明你的qt不能请求https网站,对此我们需要下载openSSL来实现qt对https的请求

openSSL的网站为:http://slproweb.com/products/Win32OpenSSL.html

下载对应的exe,注意要对应你的Qt的64/32位,下Light版本的就可以。

下载完之后的后续操作可以阅读这篇文章:https://www.cnblogs.com/zhuchunlin/p/18431631

 

8、使用Http协议进行通信

在使用Qt框架进行应用开发的过程中,很多时候需要进行客户端与服务端的网络通信,这时候就需要Qt的internet模块。而网络通信中最常用的协议就是http协议,Qt对http协议的调用进行了封装,使用非常方便。这里对常用的http请求demo做一下总结,方便大家参考。

在使用internet模块时需要在pro文件中添加对应的模块。

QT += network

Qt中使用Http协议与服务端通信的请求主要分为GET和POST,GET是从指定的资源请求数据,而POST是向指定的资源提交要被处理的数据。

常用的请求类型包括五类:

1.多个独立参数GET请求

2.参数数组GET请求

3.上传参数数据POST请求

4.上传参数和文件POST请求

5.下载文件GET请求

下面通过简单的Demo描述五种请求的调用方式。

 

1.多个独立参数GET请求

int NormalGetRequest(QString paramer1, QString paramer2)
{
    //生成对应的网络请求
    QNetworkRequest request;
    QString scheme = "http";
    QString serverAddr = "192.168.0.1";
    QString port = "80";
    QString requestHeader = scheme + QString("://") + serverAddr + QString(":") + port;
    QString fullRequest = requestHeader + QString("/api/vi/user/getrequest?paramer1=%1&paramer2=%2").arg(paramer1).arg(paramer2);
    request.setUrl(QUrl(fullRequest));
 
    //发送Get请求
    QNetworkAccessManager manager;
    QNetworkReply *reply = manager.get(request);
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
 
    //对请求的返回异常进行处理
    if(reply->error() != QNetworkReply::NoError)
    {
        return reply->error();
    }
 
    //解析返回的Json结果
    QByteArray replyData = reply->readAll();
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(replyData, &json_error));
    if(json_error.error != QJsonParseError::NoError)
    {
        return -1;
    }
    QJsonObject rootObj = jsonDoc.object();
    QString codeStr = rootObj.value("code").toString();
    if (codeStr.compare("200") == 0)
    {
        //返回代码为200的时候证明请求成功对包含的结构数据进行处理
        if(rootObj.contains("result"))
        {
 
        }
        return 0;
    }
    else
    {
        //请求失败对对应的处理
        return codeStr.toInt();
    }
}

 

2.参数数组GET请求

int GetRequestWithArray(QVector<QString> m_filePathVector)
{ 
    QJsonArray array;
    for(int index=0; index<m_filePathVector.size(); ++index)
    {
        QJsonObject object;
        object.insert("index",QString::number(index));
        object.insert("path",m_filePathVector.at(index));
        array.append(object);
    }
 
    QJsonDocument document;
    document.setArray(array);
    QString arrayString = document.toJson(QJsonDocument::Compact);
 
    //生成对应的网络请求
    QNetworkRequest request;
    QString scheme = "http";
    QString serverAddr = "192.168.0.1";
    QString port = "80";
    QString requestHeader = scheme + QString("://") + serverAddr + QString(":") + port;
    QString fullRequest = requestHeader + QString("/api/vi/user/getarray?paramers=%1").arg(arrayString);
    request.setUrl(QUrl(fullRequest));
 
    //获取错误
    QNetworkAccessManager manager;
    QNetworkReply *reply = manager.get(request);
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    if(reply->error() != QNetworkReply::NoError)
    {
        return reply->error();
    }
 
    //解析返回的Json结果
    QByteArray replyData = reply->readAll();
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(replyData, &json_error));
    if(json_error.error != QJsonParseError::NoError)
    {
        return -1;
    }
    QJsonObject rootObj = jsonDoc.object();
    QString codeStr = rootObj.value("code").toString();
    if (codeStr.compare("200") == 0)
    {
        //返回代码为200的时候证明请求成功对包含的结构数据进行处理
        if(rootObj.contains("result"))
        {
 
        }
        return 0;
    }
    else
    {
        //请求失败对对应的处理
        return codeStr.toInt();
    }
}

 

3.上传参数数据POST请求

int NormalPostRequest(QString paramer1, QString paramer2)
{
    //生成对应的网址请求
    QNetworkRequest request;
    QString scheme = "http";
    QString serverAddr = "192.168.0.1";
    QString port = "80";
    QString requestHeader = scheme + QString("://") + serverAddr + QString(":") + port;
    QString fullRequest = requestHeader + "/api/v1/user/postrequest";
    request.setUrl(QUrl(fullRequest));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
 
    //获取对应的参数数据
    QByteArray data;
    data.append("paramer1=");
    data.append(paramer1.toUtf8());
    data.append("&paramer2=");
    data.append(paramer2.toUtf8());
 
    //发送请求
    QNetworkAccessManager manager;
    QNetworkReply *reply = manager.post(request,data);
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    if(reply->error() != QNetworkReply::NoError)
    {
        return reply->error();
    }
 
 
    //解析返回的Json结果
    QByteArray replyData = reply->readAll();
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(replyData, &json_error));
    if(json_error.error != QJsonParseError::NoError)
    {
        return -1;
    }
    QJsonObject rootObj = jsonDoc.object();
    QString codeStr = rootObj.value("code").toString();
    if (codeStr.compare("200") == 0)
    {
        //返回代码为200的时候证明请求成功对包含的结构数据进行处理
        if(rootObj.contains("result"))
        {
 
        }
        return 0;
    }
    else
    {
        //请求失败对对应的处理
        return codeStr.toInt();
    }
}

 

4.上传参数和文件POST请求

int PostRequestWithFile(QString paramer1, QString paramer2,QString filePath)
{
 
    //生成对应的网址请求
    QFileInfo fileInfo(filePath);
    QString fileName =fileInfo.fileName();
 
    QFile* inputFile = new QFile(filePath);
    inputFile->open(QIODevice::ReadOnly);
 
    //multipart请求
    QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    //文件块
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                                 QVariant(QString("form-data; name=\"uploadfile\";filename=\"%1\"").arg(fileName)));
    filePart.setBodyDevice(inputFile);
    inputFile->setParent(multiPart);
    multiPart->append(filePart);
 
    QHttpPart paramer1Part;
    paramer1Part.setHeader(QNetworkRequest::ContentDispositionHeader,QVariant("form-data; name=\"paramer1\""));
    paramer1Part.setBody(paramer1.toUtf8());
    multiPart->append(paramer1Part);
 
    QHttpPart paramer2Part;
    paramer2Part.setHeader(QNetworkRequest::ContentDispositionHeader,QVariant("form-data; name=\"paramer2\""));
    paramer2Part.setBody(paramer2.toUtf8());
    multiPart->append(paramer2Part);
 
 
    //生成对应的网址请求
    QNetworkRequest request;
    QString scheme = "http";
    QString serverAddr = "192.168.0.1";
    QString port = "80";
    QString requestHeader = scheme + QString("://") + serverAddr + QString(":") + port;
    QString fullRequest = requestHeader + "/api/v1/user/postrequestwithfile";
    request.setUrl(QUrl(fullRequest));
 
    //发送请求
    QNetworkAccessManager manager;
    QNetworkReply *reply = manager.post(request,multiPart);
    multiPart->setParent(reply);
 
    QEventLoop eventLoop;
    QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
 
    if(reply->error() != QNetworkReply::NoError)
    {
        return reply->error();
    }
 
    //解析返回的Json结果
    QByteArray replyData = reply->readAll();
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(replyData, &json_error));
    if(json_error.error != QJsonParseError::NoError)
    {
        return -1;
    }
    QJsonObject rootObj = jsonDoc.object();
    QString codeStr = rootObj.value("code").toString();
    if (codeStr.compare("200") == 0)
    {
        //返回代码为200的时候证明请求成功对包含的结构数据进行处理
        if(rootObj.contains("result"))
        {
 
        }
        return 0;
    }
    else
    {
        //请求失败对对应的处理
        return codeStr.toInt();
    }
}

 

5. 下载文件GET请求

int DownloadFileFromWeb(QString fileUrl,QString&fileSavePath)
{
    QNetworkRequest request;
    QUrl url(fileUrl);
    QFileInfo fileInfo(url.path());
    QString fileName = fileInfo.fileName();
    QNetworkAccessManager *accessManager=new QNetworkAccessManager();
    request.setUrl(url);
    QNetworkReply *reply  = accessManager->get(request);
    QEventLoop loop;
    QObject::connect(accessManager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()));
//如果需要下载进度需要关联对应的信号
//connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(LoadProgress(qint64, qint64)));
    loop.exec(QEventLoop::ExcludeUserInputEvents);
 
    //获取下载返回值
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (statusCode.toInt() != 200)
    {
        return -1;
    }
 
    //保存下载的文件
    QFile file(fileSavePath);
    if(!file.open(QIODevice::WriteOnly))
    {
        return -2;
    }
    file.write(reply->readAll());
    file.close();
    return 0;
}
 

 

posted @   [BORUTO]  阅读(811)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示