博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
QT学习笔记(四):Http下载的另一种实现方式,使用QNetworkAccessManager
阅读量:5915 次
发布时间:2019-06-19

本文共 4620 字,大约阅读时间需要 15 分钟。

 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 */
}

转载地址:http://oogpx.baihongyu.com/

你可能感兴趣的文章
virtualbox 在windows7上安装
查看>>
iOS Http请求异步请求
查看>>
char、varchar 如何设置索引的长度?
查看>>
git日常使用
查看>>
初体验Jenkins安装并进行Maven项目自动化部署
查看>>
GNOME 3.2 发布
查看>>
实现sso 的两种方案
查看>>
【汇编】C++ 函数调用之——有参无返回调用(传引用)
查看>>
【汇编】C++递归调用实现
查看>>
maven 项目,通过maven编译 解决出现JSP NullPointerException
查看>>
log4j2之简化封装,告别静态成员变量
查看>>
Notadd 应用配置数据导入导出设计
查看>>
插件学习:metisMenu.min.js
查看>>
GitHub 开源的 MySQL 在线更改 Schema 工具
查看>>
(转) Twisted :第十六部分 Twisted 进程守护
查看>>
python3 使用threading模块进行多线程编码实现
查看>>
Java String和Date的转换
查看>>
MySQL 每秒插入10万行数据的方法
查看>>
JavaScript继承(四)——原型式继承
查看>>
Greenplum 数据的装载与卸载
查看>>