[SOLVED] QFtp to get QStringList of remote files



  • Hi.

    I am about to get mad on this one, so, please, just bear with me.

    I really have no idea why QFtp is so complicated and I am about giving up and turning to any of the regular c or c++ libs, that just work (tm). But, anyway...

    What I've done, so far, is as follows.

    In my constructor, I am initializing the ftp connection like this:

    @
    ///
    /// FTP stuff
    ///

    ftp = new QFtp;
    ftp->connectToHost("moo.cow");
    ftp->setTransferMode(QFtp::Passive);
    ftp->login("foo", "bar");
    ftp->cd(QString("/"));
    lista_archivos_ftp = new QStringList;
    ftp->list("/*.jpg");
    
    //ftp.cd("img_art");
    
    connect(ftp, SIGNAL(dataTransferProgress(qint64, qint64)),
            this, SLOT(my_gestor_progreso(qint64, qint64)));
    
    connect(ftp, SIGNAL(commandStarted(int)),
            this, SLOT(my_empieza_comando_ftp(int)));
    
    connect(ftp, SIGNAL(commandFinished(int,bool)),
            this, SLOT(my_acaba_comando_ftp(int,bool)));
    
    connect(ftp, SIGNAL(done(bool)),
            this, SLOT(my_hecho_ftp(bool)));
    
    connect(ftp, SIGNAL(stateChanged(int)),
            this, SLOT(my_estado_cambiado_ftp(int)));
    
    connect(ftp, SIGNAL(listInfo(QUrlInfo)),
            this, SLOT(my_list_list_ftp(QUrlInfo)));
    

    @

    I don't think it's necessary to paste all the connected code, so I'll just show you the relevant bits (just ask if you need anything more).

    @
    void kooker::my_list_list_ftp(QUrlInfo url)
    {
    my_print_log(QString(Q_FUNC_INFO).append(url.name()));
    lista_archivos_ftp->append(url.name());
    }

    void kooker::my_acaba_comando_ftp(int comando, bool error)
    {
    if(error)
    {
    my_print_log(QString("Comando FTP %1 devolvió error: %2")
    .arg(comando)
    .arg(ftp->errorString()));
    }
    else
    {
    my_print_log(QString("Comando FTP %1 se completó sin errores.")
    .arg(comando));

        int c = ftp->currentCommand();
        if(ftp->currentCommand() == QFtp::List)
            on_btn_descargar_clicked();
    }
    

    }

    void kooker::on_btn_descargar_clicked()
    {
    QEventLoop loop;
    connect(ftp, SIGNAL(commandFinished(int,bool)),
    &loop, SLOT(quit()));

    QString item;
    foreach(item, *lista_archivos_ftp)
    {
        QString img_local_path = QString(photoDir->path().append("/%1").arg(item));
        QFile *file = new QFile(img_local_path);
    
        if(!file->open(QIODevice::WriteOnly))
        {
            delete file;
            return;
        }
    
        QString ftp_file = QString("/%1").arg(item);
        ftp->get(ftp_file, file);
        loop.exec();
    
        file->close();
    }
    

    }
    @

    The thing seems to eternally hang on the loop, and never go further, a single file (since the loop doesn't go on) is created, with zero length.

    I have also tried to put file->close() in the slot called when commandFinished(), but it doesn't really work. This same on_btn_descargar_clicked() slot works without a flaw when I click the relevant button. But that's not really an option. This must be done automatically, without user interaction.

    I suspect this silly QFtp stuff is blocking the signals, that would explain why the loop never ends when I call the function from inside one of the QFtp member functions (commandFinished()). I have no idea how to check that the Get command has ended for a given file, so I can close the damn file and save it adequately. This is all my own inference, so I might very well be completely wrong in everything I exposed.

    However, while researching on this during the past few days I've found that they are ditching down QFtp in qt5, so I think I am not the only QFtp hater out there. Is there any other relevant alternative in the Qt world? What's your advice on this if I want to continue maintaining this for a long time? I don't want to waste any more time than necessary on this if in one or two years I will be having to rewrite this using libcurl anyway...

    Thanks for reading. Any tip is welcome :(

    POSTDATA:
    I forgot, I also tried the loop-less version, like this

    @
    void kooker::my_acaba_comando_ftp(int comando, bool error)
    {
    if(error)
    {
    my_print_log(QString("Comando FTP %1 devolvió error: %2")
    .arg(comando)
    .arg(ftp->errorString()));
    }
    else
    {
    my_print_log(QString("Comando FTP %1 se completó sin errores.")
    .arg(comando));

        int c = ftp->currentCommand();
        if(ftp->currentCommand() == QFtp::List)
            on_btn_descargar_clicked();
    
        if(ftp->currentCommand() == QFtp::Get)
            ftp_local_file->close();
    }
    

    }

    void kooker::on_btn_descargar_clicked()
    {
    //QEventLoop loop;

    //connect(ftp, SIGNAL(commandFinished(int,bool)),
    //        &loop, SLOT(quit()));
    
    QString item;
    foreach(item, *lista_archivos_ftp)
    {
        QString img_local_path = QString(photoDir->path().append("/%1").arg(item));
        //QFile *file = new QFile(img_local_path);
        ftp_local_file = new QFile(img_local_path);
    
        if(!ftp_local_file->open(QIODevice::WriteOnly))
        {
            delete ftp_local_file;
            return;
        }
    
        QString ftp_file = QString("/%1").arg(item);
        ftp->get(ftp_file, ftp_local_file);
        //loop.exec();
    
        //file->close();
    }
    

    }
    @

    In this case, it doesn't block, ALL the files are created in the local folder, but, the files are still empty.



  • It only took me one week to figure this one out, so I'll better post it here for future reference.

    Ripping out the loop seemed to work.

    @void kooker::fetchFtpList()
    {
    qDebug() << Q_FUNC_INFO << "Entering...";
    if(!ftp_file_list->isEmpty())
    {
    QString item = ftp_file_list->takeFirst();
    QString img_local_path = QString(photoDir->path().append("/%1").arg(item));
    ftp_local_file = new QFile(img_local_path);

        if(!ftp_local_file->open(QIODevice::WriteOnly&#41;)
        {
            delete ftp_local_file;
            return;
        }
    
        QString ftp_file = QString("/%1").arg(item);
        ftp->get(ftp_file, ftp_local_file);
    }
    //}
    

    }

    void kooker::my_commandFinished(int command, bool error)
    {
    if(error)
    {
    qDebug() << QString("FTP command %1 returned: '%2'")
    .arg(command)
    .arg(ftp->errorString());
    }
    else
    {
    if(ftp->currentCommand() == QFtp::List)
    fetchFtpList();

        if(ftp->currentCommand() == QFtp::Get)
        {
            qDebug() << Q_FUNC_INFO << QString("closing file associated with command %1, %2 bytes")
                        .arg(command)
                        .arg(ftp_local_file->size());
            ftp_local_file->close();
            fetchFtpList();
        }
    }
    

    }@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.