zoukankan      html  css  js  c++  java
  • Qt使用QNetworkAccessManager实现Http操作

    博客地址已更改,文章数量较多不便批量修改,若想访问源文请到 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接口介绍

    官方文档:QNetworkAccessManager

    接口很多,就不全部复制过来了,如果机器装着qt5,可以直接在助手看。

    可以一目了然的看到几个熟悉词汇的api:post、get、put、head,当然还有几个cookie相关的方法。

    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分别表示不同项:

    ConstantValueDescription
    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操作
  • 相关阅读:
    解密时遇到 填充无效 无法被移除
    固态硬盘SSD,机械硬盘HDD,4K速度对比。
    onsubmit ajax return false 无效
    chrome flash
    ubuntu base make 未找到命令
    winrar 压缩命令
    查看耗时长,CPU 100% 的SQL
    【转】SQL Server日志文件过大 大日志文件清理方法 不分离数据库
    安装老版本redis .NET 客户端
    python2.0_day22_web聊天室二
  • 原文地址:https://www.cnblogs.com/techiel/p/8027578.html
Copyright © 2011-2022 走看看