博客地址已更改,文章數量較多不便批量修改,若想訪問源文請到 coologic博客 查閱,網址:www.coologic.cn
如本文記錄地址為 techieliang.com/A/B/C/ 請改為 www.coologic.cn/A/B/C/ 即可查閱
版權聲明:若無來源注明, Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址:
本文標題:Qt使用QNetworkAccessManager實現Http操作 本文地址: https://www.techieliang.com/2017/12/649/
1. 介紹
QtNetwork是Qt網絡操作模塊,提供了基於TCP/IP的各種API,除了之前介紹過的最基礎的TCP及UDP通訊:QTcpSocket-Qt使用Tcp通訊實現服務端和客戶端、QUdpSocket-Qt使用Udp通訊實現服務端和客戶端,還提供了HTTP、HTTPS、FTP等高級API,並統一使用QNetworkAccessManager進行操作。Ftp使用請見:Qt使用QNetworkAccessManager實現Ftp操作
qt4x分別使用QFtp和QHttp,5以后統一用QNetworkAccessManager
HTTP請求方法
此節內容來源:HTTP請求方法
根據HTTP標准,HTTP請求可以使用多種請求方法。
HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
序號 | 方法 | 描述 |
---|---|---|
1 | GET | 請求指定的頁面信息,並返回實體主體。 |
2 | HEAD | 類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 |
3 | POST | 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。 |
4 | PUT | 從客戶端向服務器傳送的數據取代指定的文檔的內容。 |
5 | DELETE | 請求服務器刪除指定的頁面。 |
6 | CONNECT | HTTP/1.1協議中預留給能夠將連接改為管道方式的代理服務器。 |
7 | OPTIONS | 允許客戶端查看服務器的性能。 |
8 | TRACE | 回顯服務器收到的請求,主要用於測試或診斷。 |
2. QNetworkAccessManager接口介紹
接口很多,就不全部復制過來了,如果機器裝着qt5,可以直接在助手看。
可以一目了然的看到幾個熟悉詞匯的api:post、get、put、head,當然還有幾個cookie相關的方法。
- QNetworkReply *get(const QNetworkRequest &request)
- QNetworkReply *head(const QNetworkRequest &request)
- bool isStrictTransportSecurityEnabled() const
- bool isStrictTransportSecurityStoreEnabled() const
- NetworkAccessibility networkAccessible() const
- QNetworkReply *post(const QNetworkRequest &request, QIODevice *data)
- QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data)
- QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
- QNetworkProxy proxy() const
- QNetworkProxyFactory *proxyFactory() const
- QNetworkReply *put(const QNetworkRequest &request, QIODevice *data)
- QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data)
- QNetworkReply *put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
可以發現使用manager還需要幾個類:QNetworkRequest 專門用於請求的,QNetworkReply 接收請求的響應
2.1. QNetworkRequest
同樣看幫助文檔:http://doc.qt.io/qt-5/qnetworkrequest.html
- void setAttribute(Attribute code, const QVariant &value)
- void setHeader(KnownHeaders header, const QVariant &value)
- void setMaximumRedirectsAllowed(int maxRedirectsAllowed)
- void setOriginatingObject(QObject *object)
- void setPriority(Priority priority)
- void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
- void setSslConfiguration(const QSslConfiguration &config)
- void setUrl(const QUrl &url)
主要就是這幾個寫方法,分別對一個請求的不同類進行配置。
客戶端發送一個HTTP請求到服務器的請求消息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求數據四個部分組成,下圖給出了請求報文的一般格式。請求行組成:請求方法+空格+url+空格+協議版本+回車符+換行符。詳情見HTTP 消息結構
對於header,qt提供了一個枚舉類型KnownHeaders分別表示不同項:
Constant | Value | Description |
---|---|---|
QNetworkRequest::ContentDispositionHeader |
6 |
Corresponds to the HTTP Content-Disposition header and contains a string containing the disposition type (for instance, attachment) and a parameter (for instance, filename). |
QNetworkRequest::ContentTypeHeader |
0 |
Corresponds to the HTTP Content-Type header and contains a string containing the media (MIME) type and any auxiliary data (for instance, charset). |
QNetworkRequest::ContentLengthHeader |
1 |
Corresponds to the HTTP Content-Length header and contains the length in bytes of the data transmitted. |
QNetworkRequest::LocationHeader |
2 |
Corresponds to the HTTP Location header and contains a URL representing the actual location of the data, including the destination URL in case of redirections. |
QNetworkRequest::LastModifiedHeader |
3 |
Corresponds to the HTTP Last-Modified header and contains a QDateTime representing the last modification date of the contents. |
QNetworkRequest::CookieHeader |
4 |
Corresponds to the HTTP Cookie header and contains a QList<QNetworkCookie> representing the cookies to be sent back to the server. |
QNetworkRequest::SetCookieHeader |
5 |
Corresponds to the HTTP Set-Cookie header and contains a QList<QNetworkCookie> representing the cookies sent by the server to be stored locally. |
QNetworkRequest::UserAgentHeader |
7 |
The User-Agent header sent by HTTP clients. |
QNetworkRequest::ServerHeader |
8 |
The Server header received by HTTP clients. |
請求類主要是進行對於地址,還給出了QUrl 類,詳情見后。
2.2. QNetworkReply
幫助文檔:http://doc.qt.io/qt-5/qnetworkreply.html
此類繼承自QIODevice,可使用QIODevice的所有接口,包括readall讀取接收的所有信息。
同時此類提供了finished信號,在響應完斥候發出此信號,可關聯自定義槽函數函數,做響應處理。
提供了attribute屬性函數,可以判斷響應的類型,比如RedirectionTargetAttribute是目標url告知進行重定向
QNetworkReply不會自動釋放空間,一定要主動處理內存釋放,可以調用QObject::deleteLater令其自動釋放空間
3. 范例
.h文件
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QtNetwork>
- #include <QFile>
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- void Get(QUrl u);
- private slots:
- void on_pushButton_clicked();
- void finished();
- private:
- Ui::MainWindow *ui;
- QNetworkAccessManager manager;
- QUrl url;
- QNetworkReply *reply;
- QString html_text;
- };
- #endif // MAINWINDOW_H
.cpp文件
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow) {
- ui->setupUi(this);
- reply = Q_NULLPTR;
- }
- MainWindow::~MainWindow() {
- delete ui;
- }
- void MainWindow::Get(QUrl u) {
- QNetworkRequest request;
- url=u;
- request.setUrl(url);
- if(reply != Q_NULLPTR) {//更改reply指向位置錢一定要保證之前的定義了自動delete
- reply->deleteLater();
- }
- reply = manager.get(request);
- qDebug() << "start get";
- connect(reply, &QNetworkReply::finished, this, &MainWindow::finished);
- }
- void MainWindow::on_pushButton_clicked() {
- html_text = "";
- Get(QUrl("http://www.baidu.com/"));
- }
- void MainWindow::finished() {
- QByteArray bytes = reply->readAll();
- const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- reply->deleteLater();
- reply = Q_NULLPTR;
- if (!redirectionTarget.isNull()) {//如果網址跳轉重新請求
- const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());
- qDebug()<<"redirectedUrl:"<<redirectedUrl.url();
- Get(redirectedUrl);
- return;
- }
- qDebug()<<"finished";
- html_text = bytes;
- qDebug()<<"get ready,read size:"<<html_text.size();
- // QFile f("result.html");//寫出文件
- // f.open(QFile::WriteOnly);
- // f.write(bytes);
- // f.close();
- }
程序很簡單 on_pushButton_clicked 作為范例的入口,當點擊按鈕時開始訪問,會傳遞百度的網址的到Get函數。
get函數中進行get操作,並把返回值的reply connect到finished槽。
finished中首先判斷響應頭是否有重定向要求,如果有重定向則銷毀當前reply並利用指定的新地址重新調用get,可以試驗“www.sina.com”會指向”www.sina.com.cn”
最后通過readll讀取所有數據並保存到文件,雙擊打開文件可以看到效果。當然不會包含圖片信息
4. 其他
4.1. post使用
post其實和get類似,只不過同時還傳遞了串數據
post(request, data)即可,其他操作完全一樣
4.2. QUrlQuery
http://techieliang.com/wp-admin/post.php?post=000&action=edit&name=techieliang
對於上述指令直接使用QUrl賦值也是可以的,但是如果后續參數一直在變動,需要自己封裝一個字符串拼接的過程。簡單的辦法是使用QUrlQuery
- QUrl url("http://techieliang.com/wp-admin/post.php");
- QUrlQuery tt;
- tt.addQueryItem("post","000");
- tt.addQueryItem("action","edit");
- tt.addQueryItem("name","techieliang");
- url.setQuery(tt);
- qDebug()<<url.url();
- tt.clear();
- tt.addQueryItem("post","000");
- url.setQuery(tt);
- qDebug()<<url.url();
- url.setUrl("http://techieliang.com/wp-admin/post.php?");
- qDebug()<<url.url();
- url.setQuery(tt);
- qDebug()<<url.url();
結果
- "http://techieliang.com/wp-admin/post.php?post=000&action=edit&name=techieliang"
- "http://techieliang.com/wp-admin/post.php?post=000"
- "http://techieliang.com/wp-admin/post.php?"
- "http://techieliang.com/wp-admin/post.php?post=000"
- setUrl會將Url改為新值,並清空Query,直接更改url后需要重新setQuery
- setQuery不會改變Url值,可以不斷的setQuery去構造不同的參數
- QUrl會自動處理url后的?若setUrl的值末尾沒有?會自動在url和query之間增加,若已經包含則不會重復