Qt使用应用层协议用到几个类QNetworkAccessManager、QNetworkRequest、QNetworkReply、QIODevice;QNetworkAccessManager允许应用程序发送网络请求并接收响应,网络访问API是围绕一个QNetworkAccessManager对象构建的,该对象持有它发送的请求的公共配置和设置。它包含代理和缓存配置,以及与此类问题相关的信号,以及可用于监控网络操作进展的应答信号(Signal)。一个QNetworkAccessManager实例对于整个Qt应用程序应该足够了。由于QNetworkAccessManager基于QObject,所以只能从它所属的线程使用它。QNetworkRequest是网络访问API的一部分,是一个持有通过网络发送请求所需信息的类。它包含一个URL和一些可用于修改请求的辅助信息。即可设置http报头(header)信息,状态码属性以及ssl配置等。QNetworkReply类包含使用QNetworkAccessManager发送的请求的数据和报头(header)。其中包含对网络资源的监控进度。
Qt中的网络访问分异步跟同步两种方式,以下代码段为异步方式:关于下载资源遇到一个大坑,就是 reply->readAll()只能使用一次,读完数据之后,Qt的IO设备会将缓存清空。
#ifndef IHTTPREQRES_H
#define IHTTPREQRES_H
#include <QtNetwork/QNetworkAccessManager>
#include <QScriptEngine>
#include <QNetworkReply>
#include <QDir>
#include <QException>
class IHttpReqRes : public QObject
{
Q_OBJECT
public:
IHttpReqRes();
//get请求
void doHttpGet(const QString& url, const QString& urpath,const QByteArray & parmdata);
//post请求
void doHttpPost(const QString& url, const QString& urpath,const QByteArray & parmdata);
//下载图片,文件等
//参数二为绝对路径
void urlDownload(const QString &url, const QString &filename);
protected:
void slot_ResponseFinished(QNetworkReply *reply);
void slotDownLoad(QNetworkReply *reply);
void downloadProcess(qint64 bytesReceived, qint64 bytesTotal);
void slot_readyRead();
private:
QNetworkAccessManager *m_netWorkAccessManager;
QNetworkReply *m_netReply;
QNetworkRequest netRequest;
QString m_strResult;
QString m_fileName;
};
#endif // IHTTPREQRES_H
#include "ihttpreqres.h"
#include <QTextCodec>
#include <QScriptValueIterator>
IHttpReqRes::IHttpReqRes()
{
m_netWorkAccessManager = new QNetworkAccessManager();
}
void IHttpReqRes::urlDownload(const QString &url, const QString &filename)
{
if (filename.isEmpty() || url.isEmpty())
return;
m_fileName = filename;
netRequest.setUrl(QUrl(url));
m_netReply = m_netWorkAccessManager->get(netRequest);
connect(m_netWorkAccessManager,&QNetworkAccessManager::finished, this,&IHttpReqRes::slotDownLoad);
//进度条
connect(m_netReply, &QNetworkReply::downloadProgress, this, &IHttpReqRes::downloadProcess);
}
void IHttpReqRes::doHttpGet(const QString& url, const QString& urpath,const QByteArray & parmdata)
{
netRequest.setUrl(QUrl(url + urpath + parmdata));
m_netReply = m_netWorkAccessManager->get(netRequest);
qDebug() <<"url:"<< m_netReply->url().toString();
connect(m_netWorkAccessManager,&QNetworkAccessManager::finished, this,&IHttpReqRes::slot_ResponseFinished);
}
void IHttpReqRes::doHttpPost(const QString &url, const QString &urpath, const QByteArray &parmdata)
{
//netRequest.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader,"application/x-www-form-urlencoded");
//netRequest.setHeader(QNetworkRequest::ContentLengthHeader, parmdata.length());
netRequest.setUrl(QUrl(url + urpath));
m_netReply = m_netWorkAccessManager->post(netRequest,parmdata);
qDebug() <<"url:"<< m_netReply->url().toString();
connect(m_netWorkAccessManager,&QNetworkAccessManager::finished, this,&IHttpReqRes::slot_ResponseFinished);
}
void IHttpReqRes::slot_ResponseFinished(QNetworkReply *reply)
{
try {
QTextCodec *codec = QTextCodec::codecForName("utf8");
if (m_netReply->attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt()!= 200)///网络报错
return;
m_strResult = codec->toUnicode(reply->readAll());
QScriptEngine engine;
QScriptValue sc = engine.evaluate("value=" + m_strResult);
int nCode = sc.property("code").toInt32();
QString sMsg = sc.property("msg").toString();
if (sc.property("data").isArray())
{
QScriptValueIterator it(sc.property("data"));
while (it.hasNext()) {
it.next();
if (it.hasNext())
qDebug()<< "结果:"<< it.value().property("strkline").toString();
}
}
qDebug() <<"返回结果: "<< m_strResult <<"code:"<< nCode <<"sMsg:"<< sMsg;
} catch (std::exception &e) {
qDebug()<<"发生异常:"<< e.what();
}
}
void IHttpReqRes::slotDownLoad(QNetworkReply *reply)
{
QFile file;
qDebug()<< "链接:"<< reply->url();
file.setFileName(m_fileName);
if (file.open(QFile::ReadWrite))
{
file.write(reply->readAll());//readAll只能用一次打印出来就buffer就清空了。
file.flush(); // 刷新文件
file.close();
}
//方法二:
//QPixmap pix;
// QByteArray data = reply->readAll();
// pix.loadFromData(data,"PNG");
// pix.save(m_fileName,"PNG",100);//文件名 图像格式 压缩率图片质量
}
void IHttpReqRes::downloadProcess(qint64 bytesReceived, qint64 bytesTotal)
{
qDebug()<<"进度:"<< bytesTotal<< " 接收:"<<bytesReceived;
}
顺便介绍一下Qt json解析用法:主要用到以下几个类
QJsonDocument、QJsonObject、QJsonArray、QJsonParseError
QTextCodec *codec = QTextCodec::codecForName("utf8");
if (m_netReply->attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt()!= 200)///网络报错
return;
m_strResult = codec->toUnicode(reply->readAll());
QJsonParseError *error=new QJsonParseError;
QJsonDocument jdc = QJsonDocument::fromJson(QByteArray(m_strResult.toStdString().data()),error);
if(error->error!=QJsonParseError::NoError)
{
qDebug()<<"parseJson:"<<error->errorString();
return;
}
if (jdc.isEmpty())
return;
QJsonObject jObj = jdc.object();
QString msg = jObj.value("msg").toString();
QJsonArray array = jObj.value("data").toArray();
int cnt = array.size();
for (int i = 0; i < cnt; ++i)
{
QString cd = array.at(i).toObject().value("chargeDate").toString();
QString cny = array.at(i).toObject().value("currency").toString();
int id = array.at(i).toObject().value("id").toInt();
QString orderNo = array.at(i).toObject().value("orderNo").toString();
double price = array.at(i).toObject().value("price").toDouble();
qDebug() << "chargeDate:"<< cd << "currency:"<< cny <<"id:"<< id << "orderNo:"<< orderNo << "price:"<< price;
}