Qt使用QNetworkAccessManager實現Http操做

版權聲明:若無來源註明, 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操做php

qt4x分別使用QFtp和QHttp,5之後統一用QNetworkAccessManagerhtml

HTTP請求方法

此節內容來源:HTTP請求方法api

根據HTTP標準,HTTP請求可使用多種請求方法。服務器

HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。cookie

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接口介紹

官方文檔:QNetworkAccessManagerapp

接口不少,就不所有複製過來了,若是機器裝着qt5,能夠直接在助手看。函數

能夠一目瞭然的看到幾個熟悉詞彙的api:post、get、put、head,固然還有幾個cookie相關的方法。post

  1. QNetworkReply *get(const QNetworkRequest &request)
  2. QNetworkReply *head(const QNetworkRequest &request)
  3. bool isStrictTransportSecurityEnabled() const
  4. bool isStrictTransportSecurityStoreEnabled() const
  5. NetworkAccessibility networkAccessible() const
  6. QNetworkReply *post(const QNetworkRequest &request, QIODevice *data)
  7. QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data)
  8. QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
  9. QNetworkProxy proxy() const
  10. QNetworkProxyFactory *proxyFactory() const
  11. QNetworkReply *put(const QNetworkRequest &request, QIODevice *data)
  12. QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data)
  13. QNetworkReply *put(const QNetworkRequest &request, QHttpMultiPart *multiPart)

能夠發現使用manager還須要幾個類:QNetworkRequest 專門用於請求的,QNetworkReply 接收請求的響應性能

2.1. QNetworkRequest

一樣看幫助文檔:http://doc.qt.io/qt-5/qnetworkrequest.html

  1. void setAttribute(Attribute code, const QVariant &value)
  2. void setHeader(KnownHeaders header, const QVariant &value)
  3. void setMaximumRedirectsAllowed(int maxRedirectsAllowed)
  4. void setOriginatingObject(QObject *object)
  5. void setPriority(Priority priority)
  6. void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
  7. void setSslConfiguration(const QSslConfiguration &config)
  8. 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文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3.  
  4. #include <QMainWindow>
  5. #include <QtNetwork>
  6. #include <QFile>
  7. namespace Ui {
  8. class MainWindow;
  9. }
  10.  
  11. class MainWindow : public QMainWindow {
  12. Q_OBJECT
  13.  
  14. public:
  15. explicit MainWindow(QWidget *parent = 0);
  16. ~MainWindow();
  17. void Get(QUrl u);
  18. private slots:
  19. void on_pushButton_clicked();
  20. void finished();
  21. private:
  22. Ui::MainWindow *ui;
  23. QNetworkAccessManager manager;
  24. QUrl url;
  25. QNetworkReply *reply;
  26. QString html_text;
  27. };
  28.  
  29. #endif // MAINWINDOW_H

.cpp文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3.  
  4. MainWindow::MainWindow(QWidget *parent) :
  5. QMainWindow(parent),
  6. ui(new Ui::MainWindow) {
  7. ui->setupUi(this);
  8. reply = Q_NULLPTR;
  9. }
  10.  
  11. MainWindow::~MainWindow() {
  12. delete ui;
  13. }
  14.  
  15. void MainWindow::Get(QUrl u) {
  16. QNetworkRequest request;
  17. url=u;
  18. request.setUrl(url);
  19. if(reply != Q_NULLPTR) {//更改reply指向位置錢必定要保證以前的定義了自動delete
  20. reply->deleteLater();
  21. }
  22. reply = manager.get(request);
  23. qDebug() << "start get";
  24. connect(reply, &QNetworkReply::finished, this, &MainWindow::finished);
  25. }
  26.  
  27. void MainWindow::on_pushButton_clicked() {
  28. html_text = "";
  29. Get(QUrl("http://www.baidu.com/"));
  30.  
  31. }
  32.  
  33. void MainWindow::finished() {
  34. QByteArray bytes = reply->readAll();
  35. const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
  36. reply->deleteLater();
  37. reply = Q_NULLPTR;
  38. if (!redirectionTarget.isNull()) {//若是網址跳轉從新請求
  39. const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());
  40. qDebug()<<"redirectedUrl:"<<redirectedUrl.url();
  41. Get(redirectedUrl);
  42. return;
  43. }
  44. qDebug()<<"finished";
  45. html_text = bytes;
  46. qDebug()<<"get ready,read size:"<<html_text.size();
  47. // QFile f("result.html");//寫出文件
  48. // f.open(QFile::WriteOnly);
  49. // f.write(bytes);
  50. // f.close();
  51. }

程序很簡單 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

  1. QUrl url("http://techieliang.com/wp-admin/post.php");
  2. QUrlQuery tt;
  3. tt.addQueryItem("post","000");
  4. tt.addQueryItem("action","edit");
  5. tt.addQueryItem("name","techieliang");
  6. url.setQuery(tt);
  7. qDebug()<<url.url();
  8. tt.clear();
  9. tt.addQueryItem("post","000");
  10. url.setQuery(tt);
  11. qDebug()<<url.url();
  12. url.setUrl("http://techieliang.com/wp-admin/post.php?");
  13. qDebug()<<url.url();
  14. url.setQuery(tt);
  15. qDebug()<<url.url();

結果

  1. "http://techieliang.com/wp-admin/post.php?post=000&action=edit&name=techieliang"
  2. "http://techieliang.com/wp-admin/post.php?post=000"
  3. "http://techieliang.com/wp-admin/post.php?"
  4. "http://techieliang.com/wp-admin/post.php?post=000"
  • setUrl會將Url改成新值,並清空Query,直接更改url後須要從新setQuery
  • setQuery不會改變Url值,能夠不斷的setQuery去構造不一樣的參數
  • QUrl會自動處理url後的?若setUrl的值末尾沒有?會自動在url和query之間增長,若已經包含則不會重複
轉載請以連接形式標明本文標題和地址: Techie亮博客 » Qt使用QNetworkAccessManager實現Http操做
相關文章
相關標籤/搜索