QHttp是Qt所提供有關網路的高階API,可以協助您進行HTTP協定的進行,QHttp發出請求時是非同步的,請求的過程中會發出相關的Signal,您可以用Slot來接收這些Signal,並進行相關的處理。
以下先示範一個最基本的QHttp使用,程式將設計一個HttpGet類別:
- HttpGet.h
#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的實作看到:
- HttpGet.cpp
#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:
- main.cpp
#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的使用有更完整的示範。