Chinaunix首页 | 论坛 | 博客
  • 博客访问: 531200
  • 博文数量: 78
  • 博客积分: 1913
  • 博客等级: 上尉
  • 技术积分: 829
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-14 21:29
文章分类

全部博文(78)

文章存档

2011年(27)

2010年(26)

2009年(20)

2008年(5)

我的朋友

分类: C/C++

2010-05-27 16:35:48

    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_OBJECT
public:
    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 */
}


这里就不作过多解释了,因为很简单,yes?
阅读(24237) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

zhangyanfeng5552013-06-05 11:02:54

急啊

zhangyanfeng5552013-06-05 11:02:38

怎么调用啊