Download dei files in apertura finestra
-
ciao!
prendendo spunto da un articolo trovato online, ho creato questa classe che dovrebbe scaricare il file dal web:
#include "downloadydl.h" DownloadYdl::DownloadYdl() {} void DownloadYdl::fileDownloaded(QNetworkReply* np) { dd = np->readAll(); np->deleteLater(); emit downloaded(); } void DownloadYdl::download() { connect(&am, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*))); QUrl url(remotePath); QNetworkRequest request(url); am.get(request); } bool DownloadYdl::check() { QString strFile = ""; #ifdef W_OS_LINUX strFile = "./ydl"; remotePath = "https://........."; #else strFile = "./ydl.exe"; remotePath = "https://......."; #endif QFile file(strFile); return QFileInfo::exists(strFile); } QByteArray DownloadYdl::downloadedData() const { return dd; }
in avvio di programma, lancio metodo check per vedere se il file già esiste.
e se non esiste lancio il download.
solo che apparentemente il file non viene scaricato.#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); check(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::check() { ydl = new DownloadYdl(); if(!ydl->check()) { qDebug() << "KO"; ydl->download(); qDebug() << "FATTO"; } }
probabilmente sbaglio qui qualcosa sugli SLOT/SIGNAL.
-
Il problema e' che non stai connettendo i segnali emessi dalla classe
DownloadYdl
.Nella funzione
MainWindow::check()
dopo la creazione di ydl, devi collegare il segnaleDownloadYdl::downloaded
con uno slot che devi dichiarare nellaMainWindow
. In tale slot dovrai chiamare la funzioneDownloadYdl::downloadedData()
che in caso positivo dovrebbe contenere il tuo file. Ti consiglio di controllare la documentazione signal/slot per aggiungere laQObject::connect
Nota: attualmente nella funzione
MainWindow::check()
c'e' un memory leak, infatti ogni volta che chiami la funzione viene allocata di nuovo la classeDownloadYdl
, sposta questa allocazione, ed eventuale connect, nel costruttore. -
ciao!
allora, ho fatto un pò di modifiche:
#include "downloadydl.h" DownloadYdl::DownloadYdl() { if(!check()) { connect(&am, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*))); QUrl url(remotePath); QNetworkRequest request(url); am.get(request); } } DownloadYdl::~DownloadYdl() {} void DownloadYdl::fileDownloaded(QNetworkReply* np) { dd = np->readAll(); np->deleteLater(); emit downloaded(); } QByteArray DownloadYdl::downloadedData() const { qDebug() << dd; qDebug() << remotePath; return dd; } bool DownloadYdl::check() { QString strFile = ""; #ifdef __linux__ strFile = "./ydl"; remotePath = "https://yt-dl.org/downloads/latest/youtube-dl"; #else strFile = "./ydl.exe"; remotePath = "https://yt-dl.org/downloads/latest/youtube-dl.exe"; #endif QFile file(strFile); return QFileInfo::exists(strFile); }
il controllo l'ho spostato qua.
poi nella mainwindow:#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ydl = new DownloadYdl(); connect(ydl, SIGNAL(downloaded()), this, SLOT(download())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::download() { ydl->downloadedData(); }
creando lo slot come mi hai detto:
private slots: void download();
in console mi esce questo:
"302" "https://yt-dl.org/downloads/latest/youtube-dl"
ma il file non viene scaricato.
-
Perche' il contenuto del file e' all'interno del
QByteArray
ritornato dalla funzioneDownloadYdl::downloadedData()
. Nella funzioneMainWindow::download()
devi creare tu il file e popolarlo con il valore ritornato daydl->downloadedData();
.Ti allego uno snippet:
{ QFile file(fileName); if (!file.open(QFile::WriteOnly)) { // Errore in apertura file return false; } auto data = ydl->downloadedData(); file.write(data); file.close(); return true; }
-
ok grazie, ho apportato queste modifiche e ha funzionato:
#include "downloadydl.h" DownloadYdl::DownloadYdl() { #ifdef __linux__ remotePath = "https://yt-dl.org/downloads/latest/youtube-dl"; #else remotePath = "https://yt-dl.org/downloads/latest/youtube-dl.exe"; #endif connect(&am, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*))); QUrl url = QUrl::fromEncoded(remotePath.toLocal8Bit()); QNetworkRequest request(url); am.get(request); } DownloadYdl::~DownloadYdl() {} void DownloadYdl::fileDownloaded(QNetworkReply* np) { dd = np->readAll(); np->deleteLater(); emit downloaded(); } QByteArray DownloadYdl::downloadedData() const { return dd; }
nella gui:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); #ifdef __linux__ strFile = "./ydl"; #else strFile = "./ydl.exe"; #endif if(!check()) { ydl = new DownloadYdl(); connect(ydl, SIGNAL(downloaded()), this, SLOT(download())); } } MainWindow::~MainWindow() { delete ui; } bool MainWindow::check() { QFile file(strFile); return QFileInfo::exists(strFile); } void MainWindow::download() { QFile file(strFile); if (!file.open(QFile::WriteOnly)) { qDebug() << "ERRORE"; } auto data = ydl->downloadedData(); file.write(data); file.close(); }
intanto grazie mille per le dritte!!
-
no scusa, come non detto.
mi crea un file, ma dentro al file mi scrive 302.io ho visto che 302 dovrebbe essere il codice HTTP relativo al redirect.
come se non trovasse l'url, ma se lo metti nel browser lo trova senza problemi.ho fatto una modifica:
void DownloadYdl::onFinished(QNetworkReply* np) { QVariant statusCode = np->attribute(QNetworkRequest::HttpStatusCodeAttribute); qDebug() << statusCode; switch(reply->error()) { case QNetworkReply::NoError: qDebug() << "No errori"; break; default: qDebug() << reply->errorString().toLatin1(); break; } dd = np->readAll(); np->deleteLater(); emit downloaded(); }
questo mi risponde così:
QVariant(int, 302) No errori
-
Il problema e' che quel link non punta al contenuto del file, ma ad un link per scaricarlo. In sostanza quello che tu stai richiedendo e' il contenuto di quel link che e'
302
, se invece richiedi un link che contiene effettivamente qualcosa allora tutto funziona:#include <QCoreApplication> #include <QDebug> #include <QFile> #include <QNetworkAccessManager> #include <QNetworkReply> int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); QNetworkAccessManager nam; QObject::connect(&nam, &QNetworkAccessManager::finished, [&](QNetworkReply* reply) { if (!reply) { qDebug() << "Null reply"; a.exit(1); return; } QFile f(QCoreApplication::applicationDirPath() + "/dl.jpg"); if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { qDebug() << "Failed to open file"; a.exit(1); return; } f.write(reply->readAll()); f.close(); reply->deleteLater(); a.exit(0); }); QNetworkRequest request(QUrl("https://media.geeksforgeeks.org/wp-content/uploads/20190719161411/cat1-225x300.jpg")); nam.get(request); return a.exec(); }
Ti direi di fare una prova con una immagine per capire se la tua logica funziona correttamente, poi provi con il tuo link.
Se quello che desideri e' un effetto stile browser, credo ci sia da cambiare completamente l'approccio.
-
ciao.
guarda, ho usato quel link per fare delle prove con wget, curl e un programmino scritto in java.
e funziona senza problemi.allora ho copiato quel file su un altro server, e ho fatto una prova da li.
e il codice ha funzionato.
evindentemente Qt ha qualche problema con quel server specifico.allora ho provato ad usare QProcess:
process = new QProcess(); if (process) { process->setEnvironment(QProcess::systemEnvironment()); process->setProcessChannelMode(QProcess::MergedChannels); process->start("wget https://yt-dl.org/downloads/latest/youtube-dl -O ydl"); process->waitForStarted(); connect(process, &QProcess::readyReadStandardOutput, this, &MainWindow::readOutput); connect(process, &QProcess::readyReadStandardError, this, &MainWindow::readError); }
questo codice funziona.
è il download diretto a quel link che non funziona.
non so se mi sono spiegato. -
This post is deleted!