QT assistant 中有关QHttp的说明,建议我们使用 QNetworkAccessManager 和 QNetworkReply 而非QHttp,因为前者的API更多,并且提供了更丰富的错误处理。
下面是利用QNetworkAccessManager 和 QNetworkReply 实现的一个http下载类,由于QNetworkAccessManager里面没有提供网络连接中断和超时的错误处理,所以中间我用了QTimer来进行这个容错处理。
下面代码里,如果发现在下载过程中网络中断,我将重新下载 所有文件 ,并且永不停悉。(maybe it's not used for u, u can comment that).
Head file:
#ifndef IHTTPDOWNLOADS_H#define IHTTPDOWNLOADS_H#include <QObject>#include <QNetworkAccessManager>#include <QUrl>#include <QFile>#include <QNetworkReply>#include <QTimer>#include <QProgressBar>class iHttpDownloadS : public QObject{ Q_OBJECTpublic: explicit iHttpDownloadS(QObject *parent = 0, QProgressBar *_progressBar = 0); ~iHttpDownloadS(); 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:public slots: void replyFinished(QNetworkReply*); /* download finished */ void replayDownloadProgress(qint64, qint64); /* downloading... */ void slotError(QNetworkReply::NetworkError); /* handle error */ void slotReadyRead();/* ready read */ void handleTimeOut(); /* handle time out */private: QNetworkAccessManager *_downloadManager; QNetworkReply *_reply; QString _errMsg; QFile _file; QProgressBar *_progressBar; QTimer *_timeOut; QString _filePath; QUrl _url;};#endif // IHTTPDOWNLOADS_H |
Implementation file:
#include "ihttpdownloads.h"#include <QDebug>iHttpDownloadS::iHttpDownloadS(QObject *parent, QProgressBar *bar) : QObject(parent), _progressBar(bar){ _downloadManager = new QNetworkAccessManager(this); _timeOut = new QTimer(this); connect(_downloadManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); connect(_timeOut, SIGNAL(timeout()), this, SLOT(handleTimeOut()));}iHttpDownloadS::~iHttpDownloadS(){ _reply->deleteLater(); _downloadManager->deleteLater();}bool iHttpDownloadS::getFileFromURL(const QUrl &url, const QString &filePath) /* get file from url which we need to download, and restore to filePath */{ /* confirm the url is valid or not */ 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 open file.")); return false; } _url = url; _filePath = filePath; _reply = _downloadManager->get(QNetworkRequest(url)); connect(_reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); connect(_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(replayDownloadProgress(qint64, qint64))); connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); return true;}const QString &iHttpDownloadS::getLastErrorMessage(){ return _errMsg;}void iHttpDownloadS::setErrorMessage(const QString &msg){ qDebug()<<msg; _errMsg = msg;}/* slots */void iHttpDownloadS::handleTimeOut(){ qDebug()<<"time out.."; _timeOut->stop(); if (_file.isOpen()) { _file.close(); } getFileFromURL(_url, _filePath); /* try again */}void iHttpDownloadS::replyFinished(QNetworkReply* reply) /* download finished */{ _file.waitForBytesWritten(10000);/* wait 10s for write to file complete, can comment this */ if (0 == _file.size()) { qDebug()<<"Nothing be downloaded."; } else { /* add our updateUI code here... */ qDebug()<<"finished"; }}void iHttpDownloadS::replayDownloadProgress(qint64 done, qint64 total) /* downloading... */{ qDebug()<<QString("%1%").arg(done / (double)total * 100); if ((0 != _progressBar) && (0 != total)) { _progressBar->setMaximum(total); _progressBar->setValue(done); }}void iHttpDownloadS::slotReadyRead() /* if this is not been fired for 30s, we trate this timeout, and the timout handle will re download the file */{ _file.write(this->_reply->readAll()); if (_timeOut->isActive()) { _timeOut->stop(); } _timeOut->start(30000);/* wait 30 seconds */}void iHttpDownloadS::slotError(QNetworkReply::NetworkError errorCode) /* handle error */{ qDebug()<<"error:"<<errorCode; setErrorMessage(QString("Error:NetworkError code:%1").arg(errorCode)); if (_file.isOpen()) { _file.close(); } getFileFromURL(_url, _filePath);/* try again */} |