利用 Qhttp 實現http下載
今天學習了一下Qt的http下載(當然,利用http也可以實現上傳), 利用的是QHttp這個類來實現, 實現方式比較簡單, 下面給出實現方法供大家參考.
我們新建一個c++ class 叫做:iHttpDownload
其頭文件為:
#ifndef IHTTPDOWNLOAD_H #define IHTTPDOWNLOAD_H #include <QObject> #include <QHttp> #include <QUrl> #include <QFile> #include <QtGui/QtGui>
class iHttpDownload : public QObject { Q_OBJECT public: explicit iHttpDownload(QObject *parent = 0, QProgressBar *bar = 0); bool getFileFromURL(const QUrl &url, const QString &filePath); /* get file from url which we need to download, and restore to filePath */
const QString &getLastErrorMessage(); /* if error occurs, use this to get the error message */ void setErrorMessage(const QString &msg); /* set _errMsg */
signals: void done();//can commint this
public slots: void getDownloadProgress(int done, int total); void finishDownload(bool);
private: QHttp _http; QString _errMsg; QFile _file; QProgressBar *_progressBar; };
#endif // IHTTPDOWNLOAD_H |
explicit iHttpDownload(QObject *parent = 0, QProgressBar *bar = 0);
explicit關鍵字為類型安全提供保障,構造時就不允許自動轉換(隱式轉換), 意思是在構造時,必須為類型安全的轉換, 否則在編譯期間便會出錯.比如你的構造函數為constructor(int),但是你在構造的時候用constructor(112.345),編譯器會自動故你將112.345轉換成整型的112再傳遞給constructor,而explicit constructor(int)則會給出編譯錯誤.(我們假設將用一個progressBar來顯示我們下載進度,這個函數將用我們)
bool getFileFromURL(const QUrl &url, const QString &filePath);
給我一個url,給我你要存儲的地址就ok了.
void getDownloadProgress(int done, int total);
void finishDownload(bool);
這里只實現兩個slot,分別響應QHttp的void dataReadProgress (int, int)--下載進度信號和 void done(bool)下載完成兩個信號.
最后定義如下四個私有成員:
QHttp _http;
QString _errMsg;
QFile _file;
QProgressBar *_progressBar;
實現文件如下:
#include "ihttpdownload.h" #include <Qtcore> #include "defines.h"
iHttpDownload::iHttpDownload(QObject *parent, QProgressBar *bar) : QObject(parent), _progressBar(bar) { connect(&_http, SIGNAL(dataReadProgress (int, int)), this, SLOT(getDownloadProgress(int, int))); /* downloading... */ connect(&_http, SIGNAL(done(bool)), this, SLOT(finishDownload(bool))); /* finish download */ }
bool iHttpDownload::getFileFromURL(const QUrl &url, const QString &filePath) { if (!url.isValid()) { setErrorMessage(QString("Error:URL has specify a invalid name.")); return false; }
if (url.scheme() != "http") { setErrorMessage(QString("Error:URL must start with 'http:'")); return false; }
if (url.path().isEmpty()) { setErrorMessage(QString("Error:URL's path is empty.")); return false; }
if (filePath.isEmpty()) { setErrorMessage(QString("Error:invalid filePath.")); return false; }
_file.setFileName(filePath);
if (!_file.open(QIODevice::WriteOnly)) { setErrorMessage(QString("Error:Cannot write file.")); return false; }
_http.setHost(url.host(), url.port(80)); _http.get(url.path(), &_file); _http.close();
return true; }
/* singnals */ void iHttpDownload::getDownloadProgress(int done, int total) { if (_progressBar == 0 ) { /* if there is no progressBar be set */ //return; } else { _progressBar->setMaximum(total); _progressBar->setValue(done);/* the progress bar will show percentage by default */ } if (0 != total) { qDebug()<<(QString("Info:download:%1%").arg(done/(double)total * 100)); } }
void iHttpDownload::finishDownload(bool error) { if (error) { setErrorMessage(_http.errorString()); } else { qDebug()<<("Info:Download success."); emit done(); }
_file.close();
}
const QString &iHttpDownload::getLastErrorMessage() { return _errMsg; } void iHttpDownload::setErrorMessage(const QString &msg) { qDebug()<<(msg); _errMsg = msg; } |
主要的代碼如下:
_http.setHost(url.host(), url.port(80));
_http.get(url.path(), &_file);
_http.close();
setHost(QString &hostName, quint16 port=80), 用來設置HTTP 服務器,默認端口為80.
get(QString &path, QIODevice *o),設置要下載的文件路徑,可以使用相對上面hostName的路徑,也可以用絕對路徑.其余的相信大家都能看懂了.
調用方法:
iHttpDownload *down = new iHttpDownload(this, <progressbar>);
down->getFileFromURL(QUrl("http://xxxxxxx"), "./xxx.dmg");
當然,這里一個好的方法是自動命名下載的文件,我們可以用QFileInfo(url.path()).fileName()來得到文件名