Qt实现的Http在线下载程序(支持断点续传)

目录

一、gitHub地址

二、功能

三、目前存在的问题

四、界面效果

五、主要代码


开发过程中遇到了一些坑,花了半天时间搞。出现了很多理论上不应该出现的bug。

做这个的目的,主要是为了巩固一下对Qt网络部分接口的使用。

思路主要是,解析URL——>获取响应头——>获取响应状态码——>请求下载——>回读当前文件字节数进行断点续传。

需要注意,访问https前,需要添加libcrypto-1_1.dll与libssl-1_1.dll到Qt\5.14.0\mingw73_32\bin或者exe目录下。

下载地址:http://slproweb.com/products/Win32OpenSSL.html

需要注意一下32位和64位,应下载与自己Qt编译器位数一致的版本。下载好后直接安装,然后到安装目录拷贝即可。

一、gitHub地址

https://github.com/KindMans/HttpDownLoad

二、功能

支持输入url网址进行在线下载,具备断点续传功能。

后期扩展:结合qml树列表与多线程,模拟出迅雷的下载效果。

 

三、目前存在的问题

QEventLoop *loop = new QEventLoop;
connect(m_netWorkManager, SIGNAL(finished(QNetworkReply*)), loop, SLOT(quit()));
m_reply = m_netWorkManager->get(request);
loop->exec();

通过以上get访问到需要跳转的url时,速度明显快于不需要跳转的。具体原因还不清楚。

 

四、界面效果

粗略的绘制了一下界面,比较丑,主要以实现效果为主。

 

五、主要代码

启动下载:

void Http::startDownLoad(const QString &url)
{
    m_url = url;
    if(m_url.isEmpty()) return;

    if(!m_IsDownloading)
    {
        //获取请求头
        QNetworkRequest request;
        QUrl url = QUrl(m_url);
        request.setUrl(url);
        m_fileName = url.fileName();
        qDebug()<<"fileName = "<<m_fileName;
        m_reply = m_netWorkManager->head(request);
        m_state = requestHead;
        getCurrentFileSize();
        connect(m_reply,SIGNAL(finished()),this,SLOT(onfinishedRequest()));
    }
}

暂停下载:

void Http::stopDownLoad()
{
    if(m_reply == nullptr) return;

    disconnect(m_reply,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
    disconnect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(onError(QNetworkReply::NetworkError)));
    disconnect(m_reply,SIGNAL(finished()),this,SLOT(onfinishedRequest()));

    m_reply->abort();
    m_reply->deleteLater();

    m_file.close();
    getCurrentFileSize();

    m_IsDownloading = false;
}

文件大小回读:

void Http::getCurrentFileSize()
{
    QFileInfo fileInfo(m_fileName);
    if(fileInfo.exists())
    {
        m_currentLoadedBytes = fileInfo.size();
    }
    else
    {
        m_currentLoadedBytes = 0;
    }
}

槽函数onfinishedRequest():

void Http::onfinishedRequest()
{
    if(m_reply==nullptr) return;

    if(m_state == requestHead)
    {       
        m_fileSize = m_reply->rawHeader("Content-Length").toInt();
        qDebug()<<"m_fileSize = "<<m_fileSize;
        if(m_currentLoadedBytes == m_fileSize)
        {
            qDebug()<<"文件已经存在!";
            return;
        }

        QEventLoop *loop = new QEventLoop;
        connect(m_netWorkManager, SIGNAL(finished(QNetworkReply*)), loop, SLOT(quit()));
        QNetworkRequest request;
        request.setUrl(m_url);
        m_reply = m_netWorkManager->get(request);
        loop->exec();

        //获取状态码
        m_statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug()<<"statusCode="<<m_statusCode;
        m_state = requestBody;
    }

    QNetworkRequest request;
    if(m_statusCode==200)
    {
        request.setUrl(m_url);
    }
    else if(m_statusCode == 302)    //存在转调url
    {
        //获取实际下载地址
        QUrl realUrl = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
        request.setUrl(realUrl);
    }
    else
    {
        return;
    }

    QString downLoadSize = QString::number(m_fileSize);
    QString selectSize = QString("bytes=%1-%2").arg(m_currentLoadedBytes).arg(downLoadSize);
    request.setRawHeader("Range",selectSize.toLatin1());
    m_reply = m_netWorkManager->get(request);

    connect(m_reply,SIGNAL(finished()),this,SLOT(onfinishedRequest()));
    connect(m_reply,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
    connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(onError(QNetworkReply::NetworkError)));
}

槽函数onReadyRead():

void Http::onReadyRead()
{
    if(m_reply==nullptr) return;

    if(!m_file.isOpen())
    {
        m_file.setFileName(m_fileName);
        m_file.open(QIODevice::WriteOnly|QIODevice::Append);
    }

    m_file.write(m_reply->readAll());

    m_downLoadedBytes =m_file.size();

    emit fileDownloadProgress(m_downLoadedBytes, m_fileSize);
    if(m_file.size() == m_fileSize)
    {
        qDebug()<<"download finished!";
        stopDownLoad();
    }
}

 

 

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读