【问题标题】:Downloading files within a QCoreApplication在 QCoreApplication 中下载文件
【发布时间】:2021-12-20 06:39:30
【问题描述】:

我在一个团队中使用 c++ 开发 QT 应用程序。除其他外,该应用程序需要从互联网下载文件。这是我为下载文件编写的代码:

int main(int argc, char *argv[]){
        QCoreApplication app(argc, argv);
        QNetworkAccessManager man;
        std::string urlc = "https://upload.wikimedia.org/wikipedia/commons/7/73/Flat_tick_icon.svg"; //Ramdom svg file
        QUrl url(QString::fromStdString(urlc));
        QNetworkRequest req(url);
        QNetworkReply* reply = man.get(req);
        QObject::connect(reply, &QNetworkReply::finished, [department, region, &reply](){
            QByteArray read = reply->readAll();
            QString savefile = QString::fromStdString("file.png");
            QFile out(savefile);
            out.open(QIODevice::WriteOnly);
            out.write(read);
            out.close();
            reply->close();
            reply->deleteLater();
            app.quit();
        });
        return app.exec();
  }

上面的代码运行良好,并在指定的 url 下载文件。但是,如果我尝试将下载的文件提取到单独的函数中(请参见下面的代码),则该程序将无法运行。事实上,它甚至从未开始下载文件。

std::string download_file(){
    QNetworkAccessManager man;
    std::string urlc = "https://upload.wikimedia.org/wikipedia/commons/7/73/Flat_tick_icon.svg"; //Ramdom svg file
    QUrl url(QString::fromStdString(urlc));
    QNetworkRequest req(url);
    QNetworkReply* reply = man.get(req);
    QObject::connect(reply, &QNetworkReply::finished, [department, region, &reply](){
        QByteArray read = reply->readAll();
        QString savefile = QString::fromStdString("file.png");
        QFile out(savefile);
        out.open(QIODevice::WriteOnly);
        out.write(read);
        out.close();
        reply->close();
        reply->deleteLater();
    });
    return "file.png";
}

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

    std::string path = download_file();
    std::cout << path << std::endl;

    return app.exec();
}

这种行为的原因是什么?

【问题讨论】:

  • 变量范围、局部变量等
  • @eyllanesc 你是什么意思?你能说得更具体点吗?
  • 下载是异步的 - 实际上,它是在 app.exec() 运行时执行的。在下载过程中,QNetworkAccessManagerQNetworkRequest 实例必须保持活动状态。这发生在您的第一个示例中,但在您的第二个示例中,它们是函数中的局部变量,并在函数返回时立即销毁,从而取消网络操作。
  • @IgorTandetnik 明白了,谢谢!

标签: c++ qt http c++11


【解决方案1】:

不同的是,QNetworkAccessManager 在第一种情况下具有更大的范围,而第二种情况只是一个局部变量,因此在尝试时会被销毁。一种解决方法是创建一个处理所有逻辑的类:

#include <QCoreApplication>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>

class Downloader: public QObject{
    Q_OBJECT
public:
    Downloader(QObject *parent=nullptr):QObject(parent){
        connect(&m_manager, &QNetworkAccessManager::finished, this, &Downloader::handle_finished);
    }
    void download(const QUrl & url, const QString & filename){
        QNetworkRequest request;
        request.setUrl(url);
        request.setAttribute(QNetworkRequest::User, filename);
        m_manager.get(request);
    }
    Q_SIGNAL void finished(bool);
private:
    void handle_finished(QNetworkReply *reply){
        bool ok = false;
        if(reply->error() == QNetworkReply::NoError){
            QByteArray read = reply->readAll();
            QString filename = reply->request().attribute(QNetworkRequest::User).toString();
            QFile out(filename);
            if(out.open(QIODevice::WriteOnly)){
                out.write(read);
                out.close();
                ok = true;
            }
        }
        else{
            qDebug() << reply->error() << reply->errorString();
        }
        reply->deleteLater();
        Q_EMIT finished(ok);
    }
    QNetworkAccessManager m_manager;
};

#include "main.moc"

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

    Downloader downloader;

    QObject::connect(&downloader, &Downloader::finished, [](bool sucess){
        qDebug() << "download" << sucess;
    });

    downloader.download(QUrl("https://upload.wikimedia.org/wikipedia/commons/7/73/Flat_tick_icon.svg"), "file.svg");

    return a.exec();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 2012-04-23
    • 2011-08-06
    • 2013-04-06
    • 1970-01-01
    • 2018-10-04
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多