[文件下载]QNetworkAccessManager下载文件偶尔出现文件大小为0的问题

时间:2021-11-29 14:01:56
请教一个问题,最近在项目中使用QT的QNetworkAccessManager类来下载文件,大部分情况文件都下载成功,但是偶尔会出现downloadProgress触发一次,然后立刻就到finished信号,读取到数据大小为0.不知道是什么原因。
代码:

#include "HttpDownload.h"


HttpDownload::HttpDownload()
{
    downloadInfoList = new QLinkedList<HttpDownloadInfo>;
    bDownloading = false;


    thread = new QThread();


    this->moveToThread(thread);
    QObject::connect(thread, SIGNAL(started()), this, SLOT(handleThreadStarted()));

    httpStream = NULL;

    thread->start();
}

HttpDownload::~HttpDownload()
{
    if(thread)
    {
        thread->quit();
        thread->wait(100);
        delete thread;
        thread = 0;
    }

    delete downloadInfoList;
}

QAtomicPointer<HttpDownload> HttpDownload::instance;
QMutex HttpDownload::instanceMutex;
HttpDownload *HttpDownload::getInstance()
{
//    HttpDownloadDebug("getInstance!");
    if (!instance)
    {
        instanceMutex.lock();
        if (!instance)
        {
            HttpDownloadDebug("create instance!");
            instance = new HttpDownload();
        }
        instanceMutex.unlock();
    }
    return instance;
}

void HttpDownload::destroy()
{
    instanceMutex.lock();
    if (instance)
    {
        delete instance;
        instance = 0;
    }
    instanceMutex.unlock();
}

void HttpDownload::handleThreadStarted()
{
    startTimer(25);
    thread->setObjectName("httpDownloadThread-"+ QString::number((int)QThread::currentThreadId()));
}

void HttpDownload::timerEvent(QTimerEvent *event)
{
//    HttpDownloadDebug("onTimerEvent! thread name is: %s", QThread::currentThread()->objectName().toUtf8().data());

    if (bDownloading)
    {
        return;
    }

    if (downloadInfoList->count() == 0)
    {
        return;
    }

    bDownloading = true;
    currentDownloadInfo = downloadInfoList->takeFirst();

    QString cacheFilePath = currentDownloadInfo.cacheFilePath;
    if (cacheFilePath != NULL)
    {
        QFile::remove(cacheFilePath);
        HttpDownloadDebug("file removed! %s", cacheFilePath.toUtf8().data());
    }

    QUrl url = currentDownloadInfo.url;
    HttpDownloadDebug("start new download process, url is: %s", url.toString().toUtf8().data());

    if (!httpStream)
    {
        httpStream = new QNetworkAccessManager();
//        QObject::connect(QThread::currentThread(), SIGNAL(finished()), httpStream, SLOT(deleteLater()));
    }
    httpReply = httpStream->get(QNetworkRequest(url));

    connect(httpReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(handleHttpProgress(qint64, qint64)));
    connect(httpReply, SIGNAL(finished()), this, SLOT(handleHttpDone()));
    connect(httpReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleHttpError(QNetworkReply::NetworkError)));

}

void HttpDownload::handleHttpProgress(qint64 bytesRead, qint64 totalBytes)
{
    if (currentDownloadInfo.fileSize == 0)
    {
        QVariant var = httpReply->header(QNetworkRequest::ContentLengthHeader);
        currentDownloadInfo.fileSize = var.toLongLong();
        HttpDownloadDebug("file size is: %d", currentDownloadInfo.fileSize);
        emit onFileSize(currentDownloadInfo.keyword, currentDownloadInfo.fileSize);
    }

    QByteArray data = httpReply->readAll();

    HttpDownloadDebug("readLen is: %d", data.length());
    currentDownloadInfo.allBytesRead += data.length();
    HttpDownloadDebug("allBytesRead is: %d", currentDownloadInfo.allBytesRead);
    QString cacheFilePath = currentDownloadInfo.cacheFilePath;
    emit onProgress(currentDownloadInfo.keyword, data, currentDownloadInfo.allBytesRead);


    HttpDownloadDebug("cacheFilePath is: %s", cacheFilePath.toUtf8().data());

}

void HttpDownload::handleHttpDone()
{
    HttpDownloadDebug("downloading finished!");

    httpReply->deleteLater();
    emit onFinish(currentDownloadInfo.keyword, false,currentDownloadInfo.allBytesRead);
    bDownloading = false;
}

void HttpDownload::handleHttpError(QNetworkReply::NetworkError errorCode)
{
    HttpDownloadDebug("error is: %d", errorCode);

    httpReply->deleteLater();
    emit onFinish(currentDownloadInfo.keyword, true , 0);

    bDownloading = false;
}


/*
 *  Interface
 */
bool HttpDownload::addRequest(QString keyword, const QUrl &url, const QString &cacheFilePath)
{
//    HttpDownloadDebug("%s", QThread::currentThread()->objectName().toUtf8().data());
    HttpDownloadDebug("keyword is: %s, url is: %s, cacheFilePath is: %s",
                      keyword.toUtf8().data(),
                      url.toString().toUtf8().data(),
                      cacheFilePath. toUtf8().data());

    if (!url.isValid())
    {
        HttpDownloadDebug("Error:URL is invalid.");
        return false;
    }

    if (url.scheme() != "http")
    {
        HttpDownloadDebug("Error:URL must start with 'http:'");
        return false;
    }

    if (url.path().isEmpty())
    {
        HttpDownloadDebug("Error:URL's path is empty.");
        return false;
    }

    int pos = cacheFilePath.lastIndexOf("/");
    QString folderPath = cacheFilePath.left(pos + 1);
    QDir *dir = new QDir;
    if (!dir->exists(folderPath))
    {
        dir->mkpath(folderPath);
    }
    delete dir;

    HttpDownloadInfo info;
    info.keyword = keyword;
    info.url = url;
    info.cacheFilePath = cacheFilePath;
    info.fileSize = 0;
    info.allBytesRead = 0;

    downloadInfoList->append(info);

    return true;
}

2 个解决方案

#1


通过 QNetworkReply 打印 header 出来看看,也许是收到了 301/302之类的消息,需要手动处理的。

#2


好的,我加一下日志试试。

#1


通过 QNetworkReply 打印 header 出来看看,也许是收到了 301/302之类的消息,需要手动处理的。

#2


好的,我加一下日志试试。