QHttp


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的使用有更完整的示範。