qt 5.15.2 网络文件下载功能

qt 5.15.2 网络文件下载功能

cpp 复制代码
#include <QCoreApplication>

#include <iostream>
#include <QFile>
#include <QTextStream>
//
#include <QtCore>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
#include <QDir>
//
#include <QStringList>
#include "downloadmanager.h"
//
int printf(QString line)
{
    std::cout<<line.toStdString()<<std::endl;
}
int printf(int line)
{
    std::cout<<line<<std::endl;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout<<"Hello World! hsg77"<<std::endl;

    QString toDirPath="C:\\data\\obj\\test";

    DownloadManager manager;
    manager.setOutDir(toDirPath);
    //manager.append(arguments);

    //打开csv文件
    QFile file("E:\\QtProject\\objDownloadTest\\GridIdx_OBJ.csv");
    std::cout<<file.fileName().toStdString()<<std::endl;
    if(file.exists())
    {
        if(file.open(QIODevice::ReadOnly))
        {
            QTextStream in(&file);

            //std::cout<<"file state="<<in.atEnd()<<std::endl;

            while(!in.atEnd())
            {
                QString line=in.readLine();
                QStringList fds=line.split("	");

                //std::cout<<line.toStdString()<<std::endl;
                //printf(fds.length());

                //处理每一行的数据
                QString fileUrl=fds.at(13);
                printf("readydown="+fileUrl);                

                if(fileUrl!="FILE_URL")
                {
                    //下载文件  fileUrl
                    QUrl url(fileUrl);
                    manager.append(url);
                }
            }
            //
        }

    }
    //
    file.close();
    std::cout<<"csv file closed"<<std::endl;

    //开始下载开始
    QObject::connect(&manager,&DownloadManager::finished,&a,&QCoreApplication::quit);

    return a.exec();
}

定义:下载管理类

DownloadManager.h

cpp 复制代码
#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H

#include <QtNetwork>
#include <QtCore>

#include "textprogressbar.h"

class DownloadManager: public QObject
{
    Q_OBJECT
public:
    explicit DownloadManager(QObject *parent = nullptr);

    void append(const QUrl &url);
    void append(const QStringList &urls);
    static QString saveFileName(const QUrl &url,const QString outDir);

    void setOutDir(const QString outDir);

signals:
    void finished();

private slots:
    void startNextDownload();
    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
    void downloadFinished();
    void downloadReadyRead();

private:
    bool isHttpRedirect() const;
    void reportRedirect();

    QNetworkAccessManager manager;
    QQueue<QUrl> downloadQueue;
    QNetworkReply *currentDownload = nullptr;
    QFile output;
    QElapsedTimer downloadTimer;
    TextProgressBar progressBar;

    int downloadedCount = 0;
    int totalCount = 0;
    QString outDir="";
};

#endif // DOWNLOADMANAGER_H

DownloadManager.cpp

cpp 复制代码
#include "downloadmanager.h"

#include <QTextStream>

#include <cstdio>

using namespace std;

DownloadManager::DownloadManager(QObject *parent)
    : QObject(parent)
{
}

void DownloadManager::append(const QStringList &urls)
{
    for (const QString &urlAsString : urls)
        append(QUrl::fromEncoded(urlAsString.toLocal8Bit()));

    if (downloadQueue.isEmpty())
        QTimer::singleShot(0, this, &DownloadManager::finished);
}

void DownloadManager::append(const QUrl &url)
{
    if (downloadQueue.isEmpty())
        QTimer::singleShot(0, this, &DownloadManager::startNextDownload);

    downloadQueue.enqueue(url);
    ++totalCount;
}

QString DownloadManager::saveFileName(const QUrl &url,const QString outDir)
{
    QString path = url.path();
    QString basename = QFileInfo(path).fileName();

    QString newFilePath=outDir+"\\"+basename;
    return newFilePath;
    //
    if (basename.isEmpty())
        basename = "download";

    if (QFile::exists(basename)) {
        // already exists, don't overwrite
        int i = 0;
        basename += '.';
        while (QFile::exists(basename + QString::number(i)))
            ++i;

        basename += QString::number(i);
    }

    return basename;
}

void DownloadManager::setOutDir(const QString outDir)
{
    this->outDir=outDir;
}

void DownloadManager::startNextDownload()
{
    if (downloadQueue.isEmpty()) {
        printf("%d/%d files downloaded successfully\n", downloadedCount, totalCount);
        emit finished();
        return;
    }

    QUrl url = downloadQueue.dequeue();

    QString filename = saveFileName(url,this->outDir);
    output.setFileName(filename);
    if (!output.open(QIODevice::WriteOnly)) {
        fprintf(stderr, "Problem opening save file '%s' for download '%s': %s\n",
                qPrintable(filename), url.toEncoded().constData(),
                qPrintable(output.errorString()));

        startNextDownload();
        return;                 // skip this download
    }

    QNetworkRequest request(url);
    currentDownload = manager.get(request);
    connect(currentDownload, &QNetworkReply::downloadProgress,
            this, &DownloadManager::downloadProgress);
    connect(currentDownload, &QNetworkReply::finished,
            this, &DownloadManager::downloadFinished);
    connect(currentDownload, &QNetworkReply::readyRead,
            this, &DownloadManager::downloadReadyRead);

    // prepare the output
    printf("Downloading %s...\n", url.toEncoded().constData());
    downloadTimer.start();
}

void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    progressBar.setStatus(bytesReceived, bytesTotal);

    // calculate the download speed
    double speed = bytesReceived * 1000.0 / downloadTimer.elapsed();
    QString unit;
    if (speed < 1024) {
        unit = "bytes/sec";
    } else if (speed < 1024*1024) {
        speed /= 1024;
        unit = "kB/s";
    } else {
        speed /= 1024*1024;
        unit = "MB/s";
    }

    progressBar.setMessage(QString::fromLatin1("%1 %2")
                               .arg(speed, 3, 'f', 1).arg(unit));
    progressBar.update();
}

void DownloadManager::downloadFinished()
{
    progressBar.clear();
    output.close();

    if (currentDownload->error()) {
        // download failed
        fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString()));
        output.remove();
    } else {
        // let's check if it was actually a redirect
        if (isHttpRedirect()) {
            reportRedirect();
            output.remove();
        } else {
            printf("Succeeded.\n");
            ++downloadedCount;
        }
    }

    currentDownload->deleteLater();
    startNextDownload();
}

void DownloadManager::downloadReadyRead()
{
    output.write(currentDownload->readAll());
}

bool DownloadManager::isHttpRedirect() const
{
    int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    return statusCode == 301 || statusCode == 302 || statusCode == 303
           || statusCode == 305 || statusCode == 307 || statusCode == 308;
}

void DownloadManager::reportRedirect()
{
    int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    QUrl requestUrl = currentDownload->request().url();
    QTextStream(stderr) << "Request: " << requestUrl.toDisplayString()
                        << " was redirected with code: " << statusCode
                        << '\n';

    QVariant target = currentDownload->attribute(QNetworkRequest::RedirectionTargetAttribute);
    if (!target.isValid())
        return;
    QUrl redirectUrl = target.toUrl();
    if (redirectUrl.isRelative())
        redirectUrl = requestUrl.resolved(redirectUrl);
    QTextStream(stderr) << "Redirected to: " << redirectUrl.toDisplayString()
                        << '\n';
}

定义进度条类

TextProgressBar.h

cpp 复制代码
#ifndef TEXTPROGRESSBAR_H
#define TEXTPROGRESSBAR_H

#include <QString>

class TextProgressBar
{
public:
    void clear();
    void update();
    void setMessage(const QString &message);
    void setStatus(qint64 value, qint64 maximum);

private:
    QString message;
    qint64 value = 0;
    qint64 maximum = -1;
    int iteration = 0;
};

#endif // TEXTPROGRESSBAR_H

TextProgressBar.cpp

cpp 复制代码
#include "textprogressbar.h"

#include <QByteArray>

#include <cstdio>

using namespace std;

void TextProgressBar::clear()
{
    printf("\n");
    fflush(stdout);

    value = 0;
    maximum = -1;
    iteration = 0;
}

void TextProgressBar::update()
{
    ++iteration;

    if (maximum > 0) {
        // we know the maximum
        // draw a progress bar
        int percent = value * 100 / maximum;
        int hashes = percent / 2;

        QByteArray progressbar(hashes, '#');
        if (percent % 2)
            progressbar += '>';

        printf("\r[%-50s] %3d%% %s     ",
               progressbar.constData(),
               percent,
               qPrintable(message));
    } else {
        // we don't know the maximum, so we can't draw a progress bar
        int center = (iteration % 48) + 1; // 50 spaces, minus 2
        QByteArray before(qMax(center - 2, 0), ' ');
        QByteArray after(qMin(center + 2, 50), ' ');

        printf("\r[%s###%s]      %s      ",
               before.constData(), after.constData(), qPrintable(message));
    }
}

void TextProgressBar::setMessage(const QString &m)
{
    message = m;
}

void TextProgressBar::setStatus(qint64 val, qint64 max)
{
    value = val;
    maximum = max;
}

--the---end---

本blog地址:http://blog.csdn.net/hsg77

相关推荐
Hemy082 小时前
QT_QUICK_BACKEND 环境变量详解(AI生成)
开发语言·qt
艾莉丝努力练剑2 小时前
深入详解C语言的循环结构:while循环、do-while循环、for循环,结合实例,讲透C语言的循环结构
c语言·开发语言·c++·学习
晨非辰3 小时前
#C语言——学习攻略:自定义类型路线--结构体--结构体类型,结构体变量的创建和初始化,结构体内存对齐,结构体传参,结构体实现位段
c语言·开发语言·经验分享·学习·其他·学习方法·visual studio
赵英英俊3 小时前
Python day43
开发语言·python
Warren984 小时前
公司项目用户密码加密方案推荐(兼顾安全、可靠与通用性)
java·开发语言·前端·javascript·vue.js·python·安全
·白小白4 小时前
【数据结构】——栈(Stack)的原理与实现
c语言·开发语言·数据结构
野犬寒鸦5 小时前
Java Stream API 中常用方法复习及项目实战示例
java·服务器·开发语言·数据库
提笔惊蚂蚁5 小时前
Python 高级语法
开发语言·python
q567315236 小时前
使用reqwest+select实现简单网页爬虫
开发语言·爬虫·golang·kotlin
郝学胜-神的一滴6 小时前
C++中的`auto`与`std::any`:功能、区别与选择建议
开发语言·c++·程序人生·算法