用户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;
};