QHttp是Qt所提供有關網路的高階API,可以協助您進行HTTP協定的進行,QHttp發出請求時是非同步的,請求的過程中會發出相關的Signal,您可以用Slot來接收這些Signal,並進行相關的處理。
以下先示範一個最基本的QHttp使用,程式將設計一個HttpGet類別:
#ifndef HTTPGET_H #define HTTPGET_H
#include <QObject>
class QUrl; class QHttp; class QFile;
class HttpGet : public QObject { Q_OBJECT
public: HttpGet(QObject *parent = 0); void downloadFile(const QUrl &url); signals: void finished(); private slots: void done(bool error); private: QHttp *http; QFile *file; };
#endif
這個HttpGet可以讓您指定檔案的URL位址,以HTTP方式取得檔案並儲存在本地端,URL在Qt中以QUrl代表,當
檔案下載完成時,會發出finished()的Signal,當QHttp所排定的全部請求完成時,會發出done()的Signal,HttpGet類
別中自定的Slot,就是用來接收QHttp的done() Signal以進行相關處理,這可以在HttpGet的實作看到:
#include <QtNetwork> #include <QFile> #include <iostream> #include "HttpGet.h" using namespace std;
HttpGet::HttpGet(QObject *parent) : QObject(parent) { http = new QHttp(this); connect(http, SIGNAL(done(bool)), this, SLOT(done(bool))); }
void HttpGet::downloadFile(const QUrl &url) { QFileInfo fileInfo(url.path()); QString fileName = fileInfo.fileName(); if (fileName.isEmpty()) { fileName = "index.html"; }
file = new QFile(fileName); if (!file->open(QIODevice::WriteOnly)) { cerr << "Unable to save the file" << endl; delete file; file = 0; return; } http->setHost(url.host(), url.port(80)); http->get(url.path(), file); http->close(); }
void HttpGet::done(bool error) { if (error) { cerr << "Error: " << qPrintable(http->errorString()) << endl; } else { cerr << "File downloaded as " << qPrintable(file->fileName()) << endl; } file->close(); delete file; file = 0; emit finished(); }
要使用Qt的網路相關類別,必須引進QtNetwork,並且必須在..pro檔案中,加入以下這行以在建構過程中使用Qt網路模組:
QT += network
當呼叫HttpGet類別的downloadFile()方法時,程式中使用QUrl的path()來取得路徑訊息,如果路徑
訊息中沒有包括檔名,就使用預設的"index.html"作為請求的對象及下載後存檔時的檔名,要使用QHttp來請求檔案時,必須使用setHost
()來設定主機及連接埠資訊,接著使用get()方法發出請求,並告知下載的檔案要到用哪個QFile來存檔。
當QHttp所有請求處理完畢後,會發出done()的Signal,程式中將之連接至HttpGet的done()來處理,處理完成之後,再發出finished()的Signal。
以下寫個簡單的程式來測試HttpGet:
#include <QCoreApplication> #include <QUrl> #include "HttpGet.h" #include <iostream> using namespace std;
int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); HttpGet getter; getter.downloadFile(QUrl("http://caterpillar.onlyfun.net/index.html")); QObject::connect(&getter, SIGNAL(finished()), &app, SLOT(quit())); return app.exec(); }
程式中將HttpGet的finished()的Signal連接至QCoreApplication的quit(),如此當下載檔案完成後,可以直接關閉應用程式。
Qt的QHttp與QFtp在使用上有許多類似的地方,可以在以上的範例看到一些特性,以下再整理出相關特性:
- 非阻斷行為,請求是非同步的。
- 您可以排定一連串的請求,每個請求都有一個Command ID,QHttp的requestStarted()與requestFinished()等Signal會帶有請求的Command ID,您可以用以追蹤請求的執行。
- 在資料傳輸的過程中,有相關的Signal可以追蹤進度,像是QHttp的dataReadProgress()、dataSendProgress()等Signal。
- 支援QIODevice的寫入(下載)與讀取(上傳),還有以QByteArray為基礎的API。
QHttp還可以針對請求標頭、HTTPS等加以處理,在Qt的線上文件中,有個QHttp的範例 Http Example,對QHttp的使用有更完整的示範。
|