利用 Qhttp 实现http下载
今天学习了一下Qt的http下载(当然,利用http也可以实现上传), 利用的是QHttp这个类来实现, 实现方式比较简单, 下面给出实现方法供大家参考.
我们新建一个c++ class 叫做:iHttpDownload
其头文件为:
#ifndef IHTTPDOWNLOAD_H #define IHTTPDOWNLOAD_H #include #include #include #include #include
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 #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 &#61;&#61; 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 !&#61; 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 &#61; msg; } |
主要的代码如下:
_http.setHost(url.host(), url.port(80));
_http.get(url.path(), &_file);
_http.close();
setHost(QString &hostName, quint16 port&#61;80), 用来设置HTTP 服务器,默认端口为80.
get(QString &path, QIODevice *o),设置要下载的文件路径,可以使用相对上面hostName的路径,也可以用绝对路径.其余的相信大家都能看懂了.
调用方法:
iHttpDownload *down &#61; new iHttpDownload(this,
down->getFileFromURL(QUrl("http://xxxxxxx"), "./xxx.dmg");
当然,这里一个好的方法是自动命名下载的文件,我们可以用QFileInfo(url.path()).fileName()来得到文件名