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();
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章