现在的位置: 首页 > 综合 > 正文

QHttp相关

2018年06月06日 ⁄ 综合 ⁄ 共 9743字 ⁄ 字号 评论关闭

关于QHttp编程的一些笔记

 

遇到两个个博客的发送都是使用cookie来标识用户的:my.opera.com以及myspace.

请求头

请求头类:QHttpRequestHeader

设置请求方式(get/post)

QHttpRequestHeader::setRequest ("POST", "请求地址"); //post

QHttpRequestHeader::setRequest ("GET", "请求地址"); //get

请求地址可以不包含Host名称

设置请求头:

void QHttpRequestHeader::setValue(const QString & key, const QString & value)//各个变量设置

void QHttpRequestHeader::setValues ( const QListQPairQString, QString & values )//批量设置

编码

发送的内容编码有两种

multipart/form-data

application/x-www-form-urlencoded

application/x-www-form-urlencoded

使用的是URL编码,在QT中使用以下code来完成转换:

QByteArray afterData = QUrl::toPercentEncoding (befData, "&=");

befData是未转换之前的数据,函数返回的是转换后的QByteArray类型的编码。

除了大小写字母以外的所有符号都使用%n的方式表示(n为字符的两位编码)

使用QHttpRequestHeader::setValue ("content-type", "application/x-www-form-urlencoded");设置请求头

multipart/form-data

使用类似以下格式的代码进行传输:

--BlogDiary2007

Content-Disposition: form-data; name="表单控件名称"

数据

--BlogDiary2007

Content-Disposition: form-data; name="表单控件名称"

数据

--BlogDiary2007--

BlogDiary2007是各数据间的分割符,每一部分前面加上两个"--",整个表单数据完成后面再加"--"表示完成。

BlogDiary2007并不是特定的,但必须与你的请求头变量的相一致。

QHttpRequestHeader::setValue ("content-type", "multipart/form-data; boundary=BlogDiary2007");

一些用过的请求头变量

变量

COOKIE COOKIE数据

HOST(此变量是必须的) 网站的HOST地址

USER_AGENT Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)

不知道为何,USER_AGENTmyspace登陆时是必须的,弄得头崩额劽加上这个才弄好。只是标志客户端的版本而已呀,难道登陆myspace需要知道我用什么浏览器吗?不知道我改成BlogDiary会怎么样。

应答头

应答头类:QHttpResponseHeader

返回的值通过QHttpResponseHeader::value ("变量");获得

应答头的cookie的值为"set-cookie:cookie",意为请求客户端设置,我登陆博客就是通过这个取得登陆身份的。

QHttp

声明:QHttp http = new QHttp ("远端服务器的Host名称");

向服务器请求数据:int QHttp::request (请求头,发送数据);//返回请求ID

返回当前的ID(接收到数据后)int QHttp::currentID ();

QHttp的请求方式类似于打印机的打印机队列一样,可以同时发送多个请求,但真正发送是按队列先后的方式发送请求。在接收到应答头后从当前ID(QHttp::currentID())知道是哪个请求返回的数据。

获得数据的长度(接收到数据后)int QHttp::bytesAvailable ();

应该与应答头的Content-Length的值一样,没验证过,但要注意的是此值可能并不是返回数据的整个大小,因为服务器可能不是一次能够发送完所有数据。

读取数据:read (读取数据缓冲, 上面bytesAvailable ()返回的大小);

获取错误QHttp::Error QHttp::error ()

信号

请求数据后,当有数据进来后将会发送若干个信号提示服务器返回结果,使用对应Slot函数进行处理。

responseHeaderReceived (const QHttpResponseHeader& resp) 应答头已返回,可从返回的头获取应答信息

requestFinished(int id, bool error) 请求完成,error==true说明有错误发生,QHttp::error ()返回错误代码

readyRead (const QHttpResponseHeader& resp): 已有数据可读,如果数据很多,可能会发送多次信号

 *****************************************************************************************

 QHttpQt所提供有关网路的高阶API,可以协助您进行HTTP协定的进行,QHttp发出请求时是非同步的,请求的过程中会发出相关的Signal,您可以用Slot来接收这些Signal,并进行相关的处理。

以下先示範一個最基本的QHttp使用,程式將設計一個HttpGet類別: 以下先示范一个最基本的QHttp使用,程式将设计一个HttpGet类别:

  • HttpGet.h HttpGet.h
 #ifndef HTTPGET_H #ifndef HTTPGET_H 
 #define HTTPGET_H #define HTTPGET_H

 #include <QObject> #include <QObject>

 class QUrl; class QUrl;
 class QHttp; class QHttp;
 class QFile; class QFile;

 class HttpGet : public QObject { class HttpGet : public QObject {
     Q_OBJECT Q_OBJECT

 public: public:
     HttpGet(QObject *parent = 0); HttpGet(QObject *parent = 0);
     void downloadFile(const QUrl &url); void downloadFile(const QUrl &url);

 signals: signals:
     void finished(); void finished();

 private slots: private slots:
     void done(bool error); void done(bool error);

 private: private:
     QHttp *http; QHttp *http;
     QFile *file; QFile *file;
 }; };

 #endif #endif


這個HttpGet可以讓您指定檔案的URL位址,以HTTP方式取得檔案並儲存在本地端,URLQt中以QUrl代表,當檔案下載完成時,會發出finished()Signal,當QHttp所排定的全部請求完成時,會發出done()SignalHttpGet類別中自定的Slot,就是用來接收QHttpdone() Signal以進行相關處理,這可以在HttpGet的實作看到: 这个HttpGet可以让您指定档案的URL位址,以HTTP方式取得档案并储存在本地端,URLQt中以QUrl代表,当档案下载完成时,会发出finished()Signal,当QHttp所排定的全部请求完成时,会发出done()SignalHttpGet类别中自定的Slot,就是用来接收QHttpdone() Signal以进行相关处理,这可以在HttpGet的实作看到:

  • HttpGet.cpp HttpGet.cpp
#include <QtNetwork> #include <QtNetwork> 
 #include <QFile> #include <QFile>
 #include <iostream> #include <iostream>
 #include "HttpGet.h" #include "HttpGet.h"
 using namespace std; using namespace std;

 HttpGet::HttpGet(QObject *parent) : QObject(parent) { HttpGet::HttpGet(QObject *parent) : QObject(parent) {
 http = new QHttp(this); http = new QHttp(this);
 connect(http, SIGNAL(done(bool)), this, SLOT(done(bool))); connect(http, SIGNAL(done(bool)), this, SLOT(done(bool)));
 }}

 void HttpGet::downloadFile(const QUrl &url) { void HttpGet::downloadFile(const QUrl &url) {
 QFileInfo fileInfo(url.path()); QFileInfo fileInfo(url.path());
 QString fileName = fileInfo.fileName(); QString fileName = fileInfo.fileName();
 if (fileName.isEmpty()) { if (fileName.isEmpty()) {
 fileName = "index.html"; fileName = "index.html";
 } }

 file = new QFile(fileName); file = new QFile(fileName);
 if (!file->open(QIODevice::WriteOnly)) { if (!file->open(QIODevice::WriteOnly)) {
 cerr << "Unable to save the file" << endl; cerr << "Unable to save the file" << endl;
 delete file; delete file;
 file = 0; file = 0;
 return; return;
 } }

 http->setHost(url.host(), url.port(80)); http->setHost(url.host(), url.port(80));
 http->get(url.path(), file); http->get(url.path(), file);
 http->close(); http->close();
 } }

 void HttpGet::done(bool error) { void HttpGet::done(bool error) {
 if (error) { if (error) {
 cerr << "Error: " << qPrintable(http->errorString()) << endl; cerr << "Error: " << qPrintable(http->errorString()) << endl;
 } else { } else {
 cerr << "File downloaded as " << qPrintable(file->fileName()) cerr << "File downloaded as " << qPrintable(file->fileName())
 << endl; << endl;
 } }
 file->close(); file->close();
 delete file; delete file;
 file = 0; file = 0;

 emit finished(); emit finished();
 } }


要使用Qt的網路相關類別,必須引進QtNetwork,並且必須在..pro檔案中,加入以下這行以在建構過程中使用Qt網路模組: 要使用Qt的网路相关类别,必须引进QtNetwork,并且必须在..pro档案中,加入以下这行以在建构过程中使用Qt网路模组:

QT += network QT += network


當呼叫HttpGet類別的downloadFile()方法時,程式中使用QUrlpath()來取得路徑訊息,如果路徑訊息中沒有包括檔名,就使用預設的"index.html"作為請求的對象及下載後存檔時的檔名,要使用QHttp來請求檔案時,必須使用setHost ()來設定主機及連接埠資訊,接著使用get()方法發出請求,並告知下載的檔案要到用哪個QFile來存檔。 当呼叫HttpGet类别的downloadFile()方法时,程式中使用QUrlpath()来取得路径讯息,如果路径讯息中没有包括档名,就使用预设的"index.html"作为请求的对象及下载后存档时的档名,要使用QHttp来请求档案时,必须使用setHost ()来设定主机及连接埠资讯,接着使用get()方法发出请求,并告知下载的档案要到用哪个QFile来存档。

QHttp所有請求處理完畢後,會發出done()Signal,程式中將之連接至HttpGetdone()來處理,處理完成之後,再發出finished()Signal QHttp所有请求处理完毕后,会发出done()Signal,程式中将之连接至HttpGetdone()来处理,处理完成之后,再发出finished()Signal

以下寫個簡單的程式來測試HttpGet 以下写个简单的程式来测试HttpGet

  • main.cpp main.cpp
 #include <QCoreApplication> #include <QCoreApplication> 
 #include <QUrl> #include <QUrl>
 #include "HttpGet.h" #include "HttpGet.h"
 #include <iostream> #include <iostream>
 using namespace std; using namespace std;

 int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
     QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);

     HttpGet getter; HttpGet getter;
     getter.downloadFile(QUrl("http://caterpillar.onlyfun.net/index.html")); getter.downloadFile(QUrl("http://caterpillar.onlyfun.net/index.html"));

     QObject::connect(&getter, SIGNAL(finished()), &app, SLOT(quit())); QObject::connect(&getter, SIGNAL(finished()), &app, SLOT(quit()));

     return app.exec(); return app.exec();
 } }


程式中將HttpGetfinished()Signal連接至QCoreApplicationquit(),如此當下載檔案完成後,可以直接關閉應用程式。 程式中将HttpGetfinished()Signal连接至QCoreApplicationquit(),如此当下载档案完成后,可以直接关闭应用程式。

QtQHttpQFtp在使用上有許多類似的地方,可以在以上的範例看到一些特性,以下再整理出相關特性: QtQHttpQFtp在使用上有许多类似的地方,可以在以上的范例看到一些特性,以下再整理出相关特性:

  • 非阻斷行為,請求是非同步的。 非阻断行为,请求是非同步的。
  • 您可以排定一連串的請求,每個請求都有一個Command IDQHttprequestStarted()requestFinished()Signal會帶有請求的Command ID,您可以用以追蹤請求的執行。 您可以排定一连串的请求,每个请求都有一个Command IDQHttprequestStarted()requestFinished()Signal会带有请求的Command ID,您可以用以追踪请求的执行。
  • 在資料傳輸的過程中,有相關的Signal可以追蹤進度,像是QHttpdataReadProgress()dataSendProgress()Signal 在资料传输的过程中,有相关的Signal可以追踪进度,像是QHttpdataReadProgress()dataSendProgress()Signal
  • 支援QIODevice的寫入(下載)與讀取(上傳),還有以QByteArray為基礎的API 支援QIODevice的写入(下载)与读取(上传),还有以QByteArray为基础的API


QHttp
還可以針對請求標頭、HTTPS等加以處理,在Qt的線上文件中,有個QHttp的範例Http Example ,對QHttp的使用有更完整的示範。 QHttp还可以针对请求标头、HTTPS等加以处理,在Qt的线上文件中,有个QHttp的范例Http Example ,对QHttp的使用有更完整的示范。

 

 ******************************************************************************************

 在Qt中使用QHttp下载带有?问号查询的Url地址内容(含源码 )

本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息、原文链接、原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途。 谢谢合作。

原文链接:在Qt中使用QHttp下载带有?问号查询的Url地址内容(含源码 )

<<C++ GUI Programming With Qt4>>这本书的第十四章介绍了用QHttp::get()函数去下载一个网页数据。但是这个例子只能处理常规的下载,也就是实现http请求中的“GET”请求,而不能实现”POST”请求。举例来说就是,QHttp::get()
能够下载 http://www.google.com/index.html
而不能下载 http://www.cuteqt.com/blog/?feed=rss
因为后者需要的下载方式不一样,可以用另外一个函数QHttp::request()来实现。

假如我们要执行上面第二个地址的请求,写出来的代码应该是下面的样子。

34     http.setHost("www.cuteqt.com/blog");

35     rssfile.setFileName("./feed.list");

36     rssfile.open(QIODevice::WriteOnly | QIODevice::Truncate);

37     QByteArray inputStr("feed=rss");

38     QHttpRequestHeader header("POST", "/blog/");

39     header.setValue("Content-Type", "application/x-www-form-urlencoded");

40     header.setValue("Host", "www.cuteqt.com/blog");

41     requestid=http.request(header,inputStr,&rssfile);

42     http.close();

34httpQHttp 类型的,设置好要访问的主机
35
rssfileQFile类型,下载的网页会存放到这个文件里
37
:这个inputStr就是我们查询的串,格式可以是key1=var1&key2=var2&key3=var3的格式
38
:设置好主机下的请求路径
40:header
里的Host值,还是这个主机名
41:
前面配置好的参数,正式发出请求,第三个参数类型是QIODevice *,如果不想存到文件里,你也可以用QBuffer。返回值requestid的作用下面会提到。
http.close();

需要注意的是,QHttp中不管是get()还是request()都是异步请求,也就是命令发出后,随即返回。在数据处理完毕的时候会有SIGNAL信号发出。request()处理完毕的信号名叫SIGNAL(requestFinished(int id,bool)),第一个参数id正是和前面request返回的requestid,以此知道是哪一个http请求处理后的返回消息。用以下函数关联信号和槽
connect(&http, SIGNAL(requestFinished(int,bool)), this, SLOT(httpReqDone(int,bool)));

 

通用代码如下:

    QList<QPair<QByteArray, QByteArray> > querylist;
    querylist=url.encodedQueryItems();
    if(querylist.size()!=0)
    {
        QByteArray querydata;
        querydata.append(querylist[0].first);
        querydata.append('=');
        querydata.append(querylist[0].second);
        for (int i = 1; i < querylist.size(); ++i) {
            querydata.append('&');
            querydata.append(querylist[i].first);
            querydata.append('=');
            querydata.append(querylist[i].second);
        }
        QHttpRequestHeader header("POST", url.path());
        header.setValue("Content-Type", "application/x-www-form-urlencoded");
        header.setValue("Host", url.host());
        http.setHost(url.host());
        http_request_id=http.request(header,querydata,&file);
        qDebug()<<querydata;
        http.close();
    }
    else
    {
        http.setHost(url.host(), url.port(80));
        http.get(url.path(), &file);
        http_request_id=0;
        http.close();
    }

抱歉!评论已关闭.