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