Qt Http Get/Post 请求进行封装,支持子线程执行

用户Qt的http接口,对http的get请求、post请求进行了另外的封装,将软件业务和底层通信进一步隔离开。支持主线程直接调用,和子线程后台调用两种方式,闲话不多,上代码。

头文件:

#ifndef HTTP_H
#define HTTP_H

#include 
#include 
#include 
#include 

class Http : public QObject
{
    Q_OBJECT
public:
    explicit Http(QObject* parent = nullptr);
    ~Http();

    //  设置同时超时时间
    inline void setPassTime(int passTime)
    {
        m_passTime = passTime;
    }

public slots:
    //  信号槽的方式,子线程执行
    void post(QString url, const QMap& formData);
    void post2(QString url, const QMap& formData);
    void post(QString url, const QByteArray& jsonData);
    void get(QString url);

signals:
    //  子线程执行完后,发出信号 data 返回的数据,bRet 网络通信结果
    void finished(const QString& data, bool bRet);

public:
    //  下面的接口也可以直接调用, 与调用者将处于同一线程
    //  http post 网络通信, passTime 超时时间
    bool post(QString url, const QMap& formData, QString& outData, int passTime = 60000);
    bool post2(QString url, const QMap& formData, QString& outData, int passTime = 60000);
    bool post(QString url, const QByteArray& jsonData, QString& resultString, int passTime = 60000);

    //  http get 请求,passTime 超时时间
    bool get(QString url, QString& outData, int passTime = 60000);

private:
    QThread* m_pThread;
    int m_passTime;     //  通信超时时间
};

#endif // HTTP_H

cpp 文件

#include "http.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

Http::Http(QObject* parent) : QObject(parent)
{
    m_passTime = 60000;
    m_pThread = new QThread(this);
    moveToThread(m_pThread);

    m_pThread->start();
}

Http::~Http()
{
    m_pThread->quit();
    m_pThread->wait();
}

void Http::post(QString url, const QMap& formData)
{
    QString outData;
    bool bRet = post(url, formData, outData, m_passTime);
    emit finished(outData, bRet);
}

void Http::post2(QString url, const QMap& formData)
{
    QString outData;
    bool bRet = post2(url, formData, outData, m_passTime);
    emit finished(outData, bRet);
}

void Http::post(QString url, const QByteArray& jsonData)
{
    QString outData;
    bool bRet = post(url, jsonData, outData, m_passTime);
    emit finished(outData, bRet);
}

void Http::get(QString url)
{
    QString outData;
    bool bRet = get(url, outData, m_passTime);
    emit finished(outData, bRet);
}

bool Http::post(QString url, const QMap& formData, QString& outData, int passTime)
{
    QNetworkRequest request;
    request.setUrl(QUrl(url));

    QHttpMultiPart multiPart(QHttpMultiPart::FormDataType);

    QHttpPart textPart;
    //   textPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    for(auto it = formData.begin(); it != formData.end(); it++)
    {
        textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QString("form-data; name=\"%1\"").arg(it.key())));
        textPart.setBody(it.value());
        multiPart.append(textPart);
    }

    request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data;boundary=" + multiPart.boundary());

    //  进行网络通信
    bool bRet = false;
    int nTimes = 2;
    for(int i = 0; i < nTimes; ++i)
    {
        QNetworkAccessManager mgr;
        QEventLoop loop;
        connect(&mgr, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);

        QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
        timer.start((passTime > 0) ? passTime : 40000);

        QNetworkReply* pReply = mgr.post(request, &multiPart);
        connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));

        loop.exec();

        //  超时,重发
        if(!timer.isActive())
        {
            qDebug() << "post to url: " << url << " over time, time = " << passTime << ", post times: " << i;
            pReply->deleteLater();
            continue;
        }
        else
        {
            timer.stop();

            //  获取发送的返回结果
            QNetworkReply::NetworkError err = pReply->error();
            if(err != QNetworkReply::NoError)
            {
                qDebug() << "Failed: " << pReply->errorString();
                bRet = false;
            }
            else
            {
                outData = QString::fromUtf8(pReply->readAll());
                qDebug() << "Result: " << outData;
                bRet = true;
            }

            pReply->deleteLater();
            break;
        }
    }

    return bRet;
}

bool Http::post(QString url, const QByteArray& jsonData, QString& resultString, int passTime)
{
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml;charset=UTF-8");

    //  进行网络通信
    bool bRet = false;
    int nTimes = 2;
    for(int i = 0; i < nTimes; ++i)
    {
        QNetworkAccessManager mgr;
        QEventLoop loop;
        connect(&mgr, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);

        QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
        timer.start((passTime > 0) ? passTime : 40000);

        QNetworkReply* pReply = mgr.post(request, jsonData);
        connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));

        loop.exec();

        //  超时,重发
        if(!timer.isActive())
        {
            qDebug() << "post to url: " << url << " over time, time = " << passTime << ", post times: " << i;
            pReply->deleteLater();
            continue;
        }
        else
        {
            timer.stop();

            //  获取发送的返回结果
            QNetworkReply::NetworkError err = pReply->error();
            if(err != QNetworkReply::NoError)
            {
                qDebug() << "Failed: " << pReply->errorString();
                bRet = false;
            }
            else
            {
                //outObj = QJsonDocument::fromJson( pReply->readAll() ).object();
                resultString = QString::fromUtf8(pReply->readAll());
                qDebug() << resultString;
                bRet = true;
            }

            pReply->deleteLater();
            break;
        }
    }

    return bRet;
}

bool Http::post2(QString url, const QMap& formData, QString& outData, int passTime)
{
    QByteArray params;
    for(auto it = formData.begin(); it != formData.end(); it ++)
    {
        params.append(it.key().toUtf8());
        params.append("=");
        params.append(it.value());
        params.append("&");
    }
    params.remove(params.length() - 1, 1);

    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
    request.setHeader(QNetworkRequest::ContentLengthHeader, params.length());

    //  进行网络通信
    bool bRet = false;
    int nTimes = 2;
    for(int i = 0; i < nTimes; ++i)
    {
        QNetworkAccessManager mgr;
        QEventLoop loop;
        connect(&mgr, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);

        QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
        timer.start((passTime > 0) ? passTime : 40000);

        QNetworkReply* pReply = mgr.post(request, params);
        connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));

        loop.exec();

        //  超时,重发
        if(!timer.isActive())
        {
            qDebug() << "post to url: " << url << " over time, time = " << passTime << ", post times: " << i;
            pReply->deleteLater();
            continue;
        }
        else
        {
            timer.stop();

            //  获取发送的返回结果
            QNetworkReply::NetworkError err = pReply->error();
            if(err != QNetworkReply::NoError)
            {
                qDebug() << "Failed: " << pReply->errorString();
                bRet = false;
            }
            else
            {
                //outObj = QJsonDocument::fromJson( pReply->readAll() ).object();
                outData = QString::fromUtf8(pReply->readAll());
                qDebug() << outData;
                bRet = true;
            }

            pReply->deleteLater();
            break;
        }
    }

    return bRet;
}

bool Http::get(QString url, QString& outData, int passTime)
{
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));

    //  进行网络通信
    bool bRet = false;
    int nTimes = 2;
    for(int i = 0; i < nTimes; ++i)
    {
        QNetworkAccessManager mgr;
        QEventLoop loop;
        connect(&mgr, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);

        QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
        timer.start((passTime > 0) ? passTime : 40000);

        QNetworkReply* pReply = mgr.get(request);
        connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));

        loop.exec();

        //  超时,重发
        if(!timer.isActive())
        {
            qDebug() << "post to url: " << url << " over time, time = " << passTime << ", post times: " << i;
            pReply->deleteLater();
            continue;
        }
        else
        {
            timer.stop();

            //  获取发送的返回结果
            QNetworkReply::NetworkError err = pReply->error();
            if(err != QNetworkReply::NoError)
            {
                qDebug() << "Failed: " << pReply->errorString();
                bRet = false;
            }
            else
            {
                //outObj = QJsonDocument::fromJson( pReply->readAll() ).object();
                outData = QString::fromUtf8(pReply->readAll());
                qDebug() << outData;
                bRet = true;
            }

            pReply->deleteLater();
            break;
        }
    }

    return bRet;
}

调用示例,仅供参考,

注意:仅供参考,请勿照抄

//同一线程
Http http1;
QString strUrl("https://www.baidu.com");    //注意:这里的地址一定要写自己的
QMap formData;         //注意:写自己的数据
formData.insert("TestData", "abcdefg");		//注意:写自己的数据,有数据就写,没有就不写
QString strResult;
//	同步调用
if (http1.post(strUrl, formData, strResult))
{
	qDebug() << strResult;    // 请求成功,做自己的操作
}

//不同线程,异步调用
class UserObj : public QObject
{
	Q_OBJECT
public:
	UserObj()
	{
		//	创建http对象
		http = new Http();
		//	绑定异步操作需要的信号和槽
		connect(this, SIGNAL(postData(QString, const QMap&)), http, SLOT(post(QString, const QMap&)));
		connect(http, SIGNAL(finished(const QString&, bool)), this, SLOT(postResult(const QString&, bool)));

		//	这里为调用,放在自己需要的函数中
		//	发送信号,异步请求数据
		QString strUrl("https://www.baidu.com");    //注意:这里的地址一定要写自己的
		QMap formData;         //注意:写自己的数据
		formData.insert("TestData", "abcdefg");		//注意:写自己的数据,有数据就写,没有就不写
		//	发送信号,在postResult槽函数等待返回结果
		emit postData(strUrl, formData);
	}

signals:
	//	通过信号异步请求数据
	void postData(QString url, const QMap& fromData);

public slots:
	//	接受请求结果
	void postResult(const QString& data, bool bRet)
	{
		//	处理返回的请求结果
		if (bRet)
		{
			qDebug() data;
		}
	}
private:
	Http* http;
};

 

你可能感兴趣的:(qt,http)