Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] QFtp to get QStringList of remote files
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] QFtp to get QStringList of remote files

Scheduled Pinned Locked Moved General and Desktop
2 Posts 1 Posters 1.8k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    i92guboj
    wrote on last edited by
    #1

    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.

    1 Reply Last reply
    0
    • I Offline
      I Offline
      i92guboj
      wrote on last edited by
      #2

      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();
          }
      }
      

      }@

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved