Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 segnale DownloadYdl::downloaded con uno slot che devi dichiarare nella MainWindow. In tale slot dovrai chiamare la funzione DownloadYdl::downloadedData() che in caso positivo dovrebbe contenere il tuo file. Ti consiglio di controllare la documentazione signal/slot per aggiungere la QObject::connect

    Nota: attualmente nella funzione MainWindow::check() c'e' un memory leak, infatti ogni volta che chiami la funzione viene allocata di nuovo la classe DownloadYdl, 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 funzione DownloadYdl::downloadedData(). Nella funzione MainWindow::download() devi creare tu il file e popolarlo con il valore ritornato da ydl->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
    


  • @fermatqt

    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.


  • Banned

    This post is deleted!

Log in to reply