使用Qt通过Post发送Json格式数据

一、简介

1.任务目标

使用Qt通过post发送Json格式数据,或者以表单形式发送数据到服务器

2.环境简介

系统:Windows 10
Qt版本:5.7

二、内容准备

1、关于Qt

1.使用Post向服务器发送数据,使用到网络编程,需要在Pro文件中加入如下语句

QT       += network

2.使用网络编程需要用到一下库文件,还有一些在本示例中用到的库文件如下

#include 
#include 
#include 
#include 
#include 
#include 

3.Qt中使用Json数据需要用到一下库文件

#include 
#include 
#include 

三、Json数据介绍

1.Json中的基础数据类型:数字 字符串 布尔值
数字:int,double,float
字符串:string
布尔值:true,false

2.Json中的常见格式如下
2.1Json对象
通常以**{}**形式存在,数据可以当成pair类型的数据,有key对应着value,每一组key-value用逗号隔开,为方便演示写成多行,也可在一行内写完,例子如下

{
"userid":"123456",
"username":"Tom",
"age":25,
"score":95,
"pass":true
}

或者一行写完

{
“userid”:“123456”,“username”:“Tom”,“age”:25,"score":95,"pass":true
}

2.2Json数组
与C++中数组类似,Json中通常数组格式为数组名:[数据1,数据2…]

"hobby":["足球","羽毛球"]

2.3Json对象与Json数组组合
一个Json对象能包含多个Json数组
一个Json数组可以包含多个Json对象

{
"userid":"123456",
"username":"Tom",
"age":25,
"hobby":[
         {"足球","羽毛球"},
         {"书法","绘画"},
]
"score":95,
"pass":true
}

3.Qt中的Json
在Qt中有专门对Json的处理库,在5.x版本之后支持,4.x版本不支持,头文件参看上面头文件部分
Json对象在Qt中使用QJsonObject
Json数组在Qt中使用QJsonArray
在Qt中还有QJsonDocment类,该类可以当作对QJsonObject和QJsonArray的翻译,主要用来读写Json文档

4.表单数据
在Qt中,也可上传表单格式的数据到服务器,不仅可以传数据,也可以传送文件,例如音乐文件(本例使用mp3格式,具体格式可以根据需求改变),图片文件(本例使用jpeg格式,具体格式可以根据需求改变),具体使用方式以及使用格式参考下文代码示例

四、使用方法

1.新建一个类,类名定义为PostSendData,该类主要为实现发送Json数据,表单方式发送文件与接收Json返回的数据的功能,头文件与CPP文件如下

1.PostSendData头文件

class PostSendData: public QObject
{
    Q_OBJECT
public:
    PostSendData(QObject * parent = nullptr);

public:
    PostSendData(QNetworkAccessManager* net_acess_manager, QUrl url, int request_type);

    ~PostSendData();

public:
    void SendJsonData();//发送Json数据
    void SendMusic();//发送音乐文件
    void SendImage();//发送图片文件

public:
    //解析Json数据
    void getJson(QJsonObject &jsonObj);

private slots:
    void finshedSlot(QNetworkReply* reply);//用来接收返回的Json数据

private:
    QNetworkAccessManager* m_net_manager;
    QUrl m_url;
    int m_request_type;
}

2.PostSendData.cpp

#include "postsenddata.h"
PostSendData::PostSendData(QNetworkAccessManager *net_acess_manager, QUrl url, int request_type)
    :m_net_manager(net_acess_manager),
      m_url(url),
      m_request_type(request_type)
{
    connect(m_net_manager,
            &QNetworkAccessManager::finished,
            this,
            &PostSendData::finshedSlot);
}

/*
 * 示例要发送的Json数据 *
{
"userid":"123456",
"username":"Tom",
"age":25,
"hobby":["足球","羽毛球"]
"score":95,
"pass":true
}
*/

void PostSendData::SendJsonData()
{
    QNetworkRequest netReq;
    netReq.setUrl(this->m_url);
    netReq.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));//post请求设置为json,才能发送josn格式文件
    //创建一个Json对象,这个Json对象就是要发送的内容,展开成Json数据如上所示
    QJsonObject jsonObj;
    jsonObj.insert("userid","123456");
    jsonObj.insert("username","Tom");
    jsonObj.insert("age",25);
    QJsonArray arryHobby;//hobby为一个Json数组,就创建一个QJsonArray对象,用来包含hobby的内容
    arryHobby.append("足球");
    arryHobby.append("羽毛球");
    jsonObj.insert("hobby",arryHobby);//将hobby这个JsonArray加入到hobby这个JsonObject中
    jsonObj.insert("score",95);
    jsonObj.insert("pass",true);

    //创建一个QJsonDocument类对象,jsonDoc可以将Json格式数据转换之后,使用post发送
    QJsonDocument jsonDoc = QJsonDocument(jsonObj);
    QByteArray post_data = jsonDoc.toJson(QJsonDocument::Compact);
    m_net_manager->post(netReq,post_data);
}

void PostSendData::SendMusic()
{
    //打开要发送的音乐文件,这里使用了一首大小为3M的歌曲,也可以具体使用时在指定要发送的音乐文件,此处方便演示直接使用绝对路径下的音乐文件
    QString filePath = "H:/Code/QT/PostTest/bin/测试.mp3";
    QFile* file = new QFile(filePath);
    file->open(QIODevice::ReadOnly);

    //发送音乐文件时,有可能还有附加的数据内容,可以预先定义好,也可发送时再定义
    QString userid = "123456";
    QString username = "Tom";

    QNetworkRequest netReq;
    netReq.setUrl(this->m_url);

/*
 * 使用QHttpMultiPart创建一个multiPart对象,我们最后要发送的就是这multiPart对象
 * multiPart中的内容,添加使用QHttpPart创建的对象
 * QHttpPart类创建的对象,因为这里发送的有数据,也有音乐文件,所以使用from-data
*/

    QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart useridPart;
    useridPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"userid\""));
    useridPart.setBody(userid.toUtf8());

    QHttpPart usernamePart;
    usernamePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"username\""));
    usernamePart.setBody(username.toUtf8());

    QHttpPart projectidPart;
    projectidPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"projectid\""));
    projectidPart.setBody("9");
    //这里将要发送的文件放入mp3Part中
    QHttpPart mp3Part;
    mp3Part.setHeader(QNetworkRequest::ContentDispositionHeader,
                      QVariant(QString("form-data; name=\"file\";filename=\"测试.mp3\";")));
    mp3Part.setBodyDevice(file);

    //将所有想发送的内容放入multiPart中
    multiPart->append(useridPart);
    multiPart->append(usernamePart);
    multiPart->append(projectidPart);
    multiPart->append(mp3Part);
    //发送
    m_net_manager->post(netReq,multiPart);
}

void PostSendData::SendImage()
{
    //与发送音乐文件类似,不过是改成图片文件
    QString filePath = "H:/Code/QT/PostTest/bin/测试.jpeg";
    QFile* file = new QFile(filePath);
    file->open(QIODevice::ReadOnly);

    QString userid = "123456";
    QString username = "Tom";

    QNetworkRequest netReq;
    netReq.setUrl(this->m_url);

    QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart useridPart;
    useridPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"userid\""));
    useridPart.setBody(userid.toUtf8());

    QHttpPart usernamePart;
    usernamePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"username\""));
    usernamePart.setBody(username.toUtf8());

    QHttpPart projectidPart;
    projectidPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"projectid\""));
    projectidPart.setBody("9");

    QHttpPart imagePart;
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                      QVariant(QString("form-data; name=\"file\";filename=\"测试.jpeg\";")));
    imagePart.setBodyDevice(file);

    multiPart->append(useridPart);
    multiPart->append(usernamePart);
    multiPart->append(projectidPart);
    multiPart->append(imagePart);

    m_net_manager->post(netReq,multiPart);
}

void PostSendData::getJson(QJsonObject &jsonObj)
{
    switch (this->m_request_type)
    {
    case SENDDATA:
    {
/*
 * 返回Json数据示例,code:1-成功,2-失败,3-用户识别失败
 * {"code":"1","msg":sucess,"result":true}
*/
        qDebug() << "------------------发送数据的返回---------------------";
        QString code = jsonObj.value("code").toString();
        qDebug() << "code = " << code;
        QString msg = jsonObj.value("msg").toString();
        qDebug() << "msg = " << msg;
        bool result = jsonObj.value("result").toBool();
        break;
    }
    case SENDMUSIC:
    {
/*
* 返回Json数据示例,code:1-成功,2-失败,3-用户识别失败
* {"code":"1","msg":sucess,"datas":[{"id":1,"music_name":"测试.mp3","music_id":456},]}
*/
        qDebug() << "------------------发送音乐的返回---------------------";
        QString code = jsonObj.value("code").toString();
        qDebug() << "code = " << code;
        QString msg = jsonObj.value("msg").toString();
        qDebug() << "msg = " << msg;

        //返回的Json数据中,datas是一个Json数组包含了Json对象,先把JsonObject转换成JsonValue
        //JsonValue转换成JsonArray,再去循环读出JsonArray的内容
        QJsonValue locationValue = jsonObj.value(QStringLiteral("datas"));
        QJsonArray locationValueArray = locationValue.toArray();
        for (int i = 0; i < locationValueArray.size(); i++)
        {
            QJsonValue locationArray = locationValueArray.at(i);
            QJsonObject location = locationArray.toObject();
            qDebug()<< "id = " << location["id"].toString();
            qDebug()<< "music_name = "<< location["music_name"].toString();
            qDebug()<< "music_id = " << location["music_id"].toString();
        }

        break;
    }
    case SENDIMAGE:
    {
/*
*与发送音乐的返回类似
* 返回Json数据示例,code:1-成功,2-失败,3-用户识别失败
* {"code":"1","msg":sucess,"datas":[{"id":1,"image_name":"测试.jepg","image_id":456},]}
*/
        qDebug() << "------------------发送图片的返回---------------------";
        QString code = jsonObj.value("code").toString();
        qDebug() << "code = " << code;
        QString msg = jsonObj.value("msg").toString();
        qDebug() << "msg = " << msg;
        QJsonValue locationValue = jsonObj.value(QStringLiteral("datas"));
        QJsonArray locationValueArray = locationValue.toArray();
        for (int i = 0; i < locationValueArray.size(); i++)
        {
            QJsonValue locationArray = locationValueArray.at(i);
            QJsonObject location = locationArray.toObject();
            qDebug()<< "id = " << location["id"].toString();
            qDebug()<< "music_name = "<< location["image_name"].toString();
            qDebug()<< "music_id = " << location["image_id"].toString();
        }
        break;
    }
    }
}

void PostSendData::finshedSlot(QNetworkReply *reply)
{
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(reply->error() == QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes);
        QJsonObject jsonObj = jsonDoc.object();
        getJson(jsonObj);
    }
    reply->deleteLater();
}

3.在MainWindown中,我添加了三个按钮,用来发送不同的内容,MainWindown的头文件不在贴出,按钮使用界面直接转到槽clicked(),只贴出MainWindown.cpp供参考

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "postsenddata.h"

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

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_pushButton_sendData_clicked()
{
    QNetworkAccessManager* m_netmanager_upwav = new QNetworkAccessManager(this);
    QUrl senddataUrl = QUrl("http://SendData");
    PostSendData* sendData= new PostSendData(m_netmanager_upwav,senddataUrl,0);
    //0对应PostSendData中枚举类型,用途是接受不同的返回,解析Json数据时能找到解析的case,下面的1和2类似
    sendData->SendJsonData();
}

void MainWindow::on_pushButton_sendMusic_clicked()
{
    QNetworkAccessManager* m_netmanager_sendmusic = new QNetworkAccessManager(this);
    QUrl sendmusicUrl = QUrl("http://SendMusic");
    PostSendData* sendMusic= new PostSendData(m_netmanager_sendmusic,sendmusicUrl,1);
    sendMusic->SendMusic();
}

void MainWindow::on_pushButton_sendImage_clicked()
{
    QNetworkAccessManager* m_netmanager_sendimage = new QNetworkAccessManager(this);
    QUrl sendimageUrl = QUrl("http://SendImage");
    PostSendData* sendImagec= new PostSendData(m_netmanager_sendimage,sendimageUrl,2);
    sendImagec->SendImage();
}

后记说明

参考了很多文档,基础使用文档很多,综合起来使用的还是比较少,要不就是需要收费,所以这算是一个在Qt中使用Post方式,向http发送Json数据,以及使用表单形式发送文件+数据的一个综合例程,仅供参考,如有问题请指出,一起探讨进步。关于Qt中对于Json以及网络接口的使用,参考Qt中的文档,还有许多使用方式,接口函数可以调用。

你可能感兴趣的:(qt,json,开发语言)