• 封装qt http文件下载类


    #include <QApplication>

    #include <QtWidgets>
    #include <QtNetwork>

    //downloads one file at a time, using a supplied QNetworkAccessManager object
    class FileDownloader : public QObject{
        Q_OBJECT
    public:
        explicit FileDownloader(QObject* parent= nullptr)
            :QObject(parent)
        {
            nam = new QNetworkAccessManager(this);
        }
        ~FileDownloader(){
            //destructor cancels the ongoing dowload (if any)
            if(networkReply){
                a_abortDownload();
            }
        }

        //call this function to start downloading a file from url to fileName
        void startDownload(QUrl url, QString fileName){
            if(networkReply) return;
            destinationFile.setFileName(fileName);
            if(!destinationFile.open(QIODevice::WriteOnly)) return;
            emit goingBusy();
            QNetworkRequest request(url);
            networkReply= nam->get(request);
            connect(networkReply, &QIODevice::readyRead, this, &FileDownloader::readData);
            connect(networkReply, &QNetworkReply::downloadProgress,
                    this, &FileDownloader::downloadProgress);
            connect(networkReply, &QNetworkReply::finished,
                    this, &FileDownloader::finishDownload);
        }

        //call this function to abort the ongoing download (if any)
        void abortDownload(){
            if(!networkReply) return;
            a_abortDownload();
            emit backReady();
        }

        //connect to the following signals to get information about the ongoing download
        Q_SIGNAL void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
        Q_SIGNAL void downloadSuccessful();
        Q_SIGNAL void downloadError(QString errorString);
        //the next two signals are used to indicate transitions between busy and
        //ready states of the file downloader, they can be used to update the GUI
        Q_SIGNAL void goingBusy();
        Q_SIGNAL void backReady();

    private:
        Q_SLOT void readData(){
            QByteArray data= networkReply->readAll();
            destinationFile.write(data);
        }
        Q_SLOT void finishDownload(){
            if(networkReply->error() != QNetworkReply::NoError){
                //failed download
                a_abortDownload();
                qDebug() << "networkReply->errorString()"<<networkReply->errorString();
                emit downloadError(networkReply->errorString());
            } else {
                //successful download
                destinationFile.close();
                networkReply->deleteLater();
                qDebug() << "downloadSuccessful";
                emit downloadSuccessful();
            }
            emit backReady();
        }
        //private function, cleans things up when the download is aborted
        //(due to an error or user interaction)
        void a_abortDownload(){
            networkReply->abort();
            networkReply->deleteLater();
            destinationFile.close();
            destinationFile.remove();
        }

        QNetworkAccessManager* nam;
        QUrl downloadUrl;
        QFile destinationFile;
        QPointer<QNetworkReply> networkReply;
    };

    //A sample GUI application that uses the above class
    class Widget : public QWidget{
        Q_OBJECT
    public:
        explicit Widget(QWidget* parent= nullptr):QWidget(parent){
            layout.addWidget(&lineEditUrl, 0, 0);
            layout.addWidget(&buttonDownload, 0, 1);
            layout.addWidget(&progressBar, 1, 0);
            layout.addWidget(&buttonAbort, 1, 1);
            layout.addWidget(&labelStatus, 2, 0, 1, 2);
            lineEditUrl.setPlaceholderText("URL to download");
            connect(&fileDownloader, &FileDownloader::downloadSuccessful,
                    this, &Widget::downloadFinished);
            connect(&fileDownloader, &FileDownloader::downloadError,
                    this, &Widget::error);
            connect(&fileDownloader, &FileDownloader::downloadProgress,
                    this, &Widget::updateProgress);
            connect(&buttonDownload, &QPushButton::clicked,
                    this, &Widget::startDownload);
            connect(&buttonAbort, &QPushButton::clicked,
                    this, &Widget::abortDownload);

            showReady();
            //use goingBusy() and backReady() from FileDownloader signals to update the GUI
            connect(&fileDownloader, &FileDownloader::goingBusy, this, &Widget::showBusy);
            connect(&fileDownloader, &FileDownloader::backReady, this, &Widget::showReady);
        }

        ~Widget() = default;

        Q_SLOT void startDownload(){
            if(lineEditUrl.text().isEmpty()){
                QMessageBox::critical(this, "Error", "Enter file Url", QMessageBox::Ok);
                return;
            }
            QString fileName =
                    QFileDialog::getSaveFileName(this, "Destination File");
            if(fileName.isEmpty()) return;
            QUrl url= lineEditUrl.text();
            fileDownloader.startDownload(url, fileName);
        }
        Q_SLOT void abortDownload(){
            fileDownloader.abortDownload();
        }

        Q_SLOT void downloadFinished(){
            labelStatus.setText("Download finished successfully");
        }
        Q_SLOT void error(QString errorString){
            labelStatus.setText(errorString);
        }
        Q_SLOT void updateProgress(qint64 bytesReceived, qint64 bytesTotal){
            progressBar.setRange(0, bytesTotal);
            progressBar.setValue(bytesReceived);
        }
    private:
        Q_SLOT void showBusy(){
            buttonDownload.setEnabled(false);
            lineEditUrl.setEnabled(false);
            buttonAbort.setEnabled(true);
            labelStatus.setText("Downloading. . .");
        }
        Q_SLOT void showReady(){
            buttonDownload.setEnabled(true);
            lineEditUrl.setEnabled(true);
            buttonAbort.setEnabled(false);
            progressBar.setRange(0,1);
            progressBar.setValue(0);
        }

        QGridLayout layout{this};
        QLineEdit lineEditUrl;
        QPushButton buttonDownload{"Start Download"};
        QProgressBar progressBar;
        QPushButton buttonAbort{"Abort Download"};
        QLabel labelStatus{"Idle"};
    //    QNetworkAccessManager nam;
    //    FileDownloader fileDownloader{&nam};
        FileDownloader fileDownloader;
    };

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

        Widget w;
        w.show();

        return a.exec();
    }

    #include "main.moc"

  • 相关阅读:
    64位win2008下IIS未开启32位支持导致DLL无法加载问题
    多控制器传递不同类型实体类到共用视图方案
    敏捷开发学习笔记——产品经理
    一些Razor语法
    敏捷开发学习笔记——用户故事与多职能团队
    UM九图
    Linq的分页
    easyUI datagrid 前端真分页
    C#项目的生成事件及批处理文件
    子类复制父类的值
  • 原文地址:https://www.cnblogs.com/cute/p/11315166.html
Copyright © 2020-2023  润新知