在 QCoreApplication 中下载文件
Downloading files within a QCoreApplication
我在一个团队中工作,使用 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();
}
造成这种行为的原因是什么?
不同之处在于,QNetworkAccessManager 在第一种情况下具有更大的范围,而第二种情况则相反,后者只是一个局部变量,因此会在尝试时被销毁。一种解决方法是创建一个 class 来处理所有逻辑:
#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();
}
我在一个团队中工作,使用 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();
}
造成这种行为的原因是什么?
不同之处在于,QNetworkAccessManager 在第一种情况下具有更大的范围,而第二种情况则相反,后者只是一个局部变量,因此会在尝试时被销毁。一种解决方法是创建一个 class 来处理所有逻辑:
#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();
}