Solved Download multiple files from Ftp issue
-
Hi! I want to download some files from my ftp server. The problem is, that only the last one has data, others 0 sized or it crashes when close
QFile
as a pointer.My code:
QFtp *ftp = new QFtp(this); ftp->connectToHost(FTP_HOST, FTP_PORT); ftp->login(FTP_USERNAME, FTP_PASSWORD); QFile *reportFile = nullptr; connect(ftp, &QFtp::listInfo, [this](const QUrlInfo &ftpUrlInfo) { if (ftpUrlInfo.isFile()) { reportFile = new QFile("some local path" + ftpUrlInfo.name()); reportFile->open(QIODevice::WriteOnly); ftp->get("some ftp path" + ftpUrlInfo.name(), reportFile, QFtp::Binary); } }); connect(ftp, &QFtp::done, [this]() { qDebug() << "DONE!"; ftp->close(); ftp->deleteLater(); }); connect(ftp, &QFtp::commandFinished, [this]() { qDebug() << "COMMAND FINISHED!"; if (reportFile != nullptr) { reportFile.close(); reportFile->deleteLater(); } }); ftp->list("ftp path to dir");
So, it should download the file, close it and
deleteLater
for all files in the ftp directory. Any ideas how to do it? Thanks. -
@Cobra91151
How are you waiting for one file'sget()
to finish, before you set off the next one? You are reusing the samereportFile
variable over & over, while it is still servicing previous fileget()
s? Hence you only get the final file, and the crashes when one file'sreportFile.close();
closes/deletes thereportFile
from a different file!? (Put aqDebug()
in the firstconnect()
, not just the other two.)Either wait if you want to do one-at-a-time synchronously, or you need to maintain multiple different
reportFile
s to do them all asynchronously. -
Ok. I will change code and reply. Thanks.
-
I have tried to use
QList<QFile*>
and append the files when they are listing, and then loop it, and when commandget()
finished, close anddeleteLater()
the file, now it doesn't crash when useQFile
as a pointer but all files are 0 sized.if (ftp->currentCommand() == QFtp::Get) { qDebug() << "GET FINISHED!"; reportFile->close(); reportFile->deleteLater(); }
I think that here is better to use
QQueue
and proceed the file one by one. -
Hi
Did you replace reportFile with access to the QList<QFile*>
so each invocation works on the right QFile?
Should work just as fine as one.
But yeah if 1 download works, than using a queue should be ok easy. -
Yes, 1 file downloads works. The problem with collection of files. I'm currently working to fix it.
-
@Cobra91151
Ok if concurrent download is not a must have, one by one should be fairly
easy to implement if 1 download already works.It sounds like you did it correctly with QList<QFile*> but you never showed
full code after the change so its unclear if just a normal bug-ish or
something with QFtp .
Also the shown connect(ftp, &QFtp::done ) would delete the ftp on first file finished
but assume you fixed that also ? -
I will post more code soon. Yes, I have fixed it by creating
closeFtp
function and connect to it when it finished, so I just need to read more docs on theQQueue
and fix the issue with the files.void Test::closeFtp() { qDebug() << "FTP CLOSED"; ftp->close(); ftp->deleteLater(); emit finished(); }
I will reply later. Thanks.
-
Hi! I have finally fixed it!
My code:
QQueue<QFile*> reportQueue; //initialize the queue connect(ftp, &QFtp::listInfo, [this](const QUrlInfo &ftpUrlInfo) { if (ftpUrlInfo.isFile()) { reportQueue.append(new QFile("local path" + "\\" + ftpUrlInfo.name())); } }); connect(ftp, &QFtp::done, [this]() { emit reportsDataFinished(); }); connect(ftp, &QFtp::commandFinished, [this]() { if (ftp->currentCommand() == QFtp::List) { proceedDownload(); } else if (ftp->currentCommand() == QFtp::Get) { reportFile->close(); reportFile->deleteLater(); proceedDownload(); } }); if (ftp->error() == QFtp::NotConnected) { emit ftpReportError(ftp->error()); } else { ftp->list("ftp path to the dir"); } void Test::proceedDownload() { if (!reportQueue.isEmpty()) { reportFile = reportQueue.dequeue(); reportFile->open(QIODevice::WriteOnly); QFileInfo ftpFileInfo(reportFile->fileName()); ftp->get("ftp path to file" + "/" + ftpFileInfo.fileName(), reportFile, QFtp::Binary); } }
I added the files to the
QQueue
, when ftplist
command has been finished, I use functionproceedDownload()
. In the function, Idequeue()
the queue to thereportFile
and proceed with ftpget()
function. Whenget
ftp command finishes, Iclose
anddelete
the file from memory, and again call theproceedDownload()
. So the the whole process goes again until the queue is empty. I useemit reportsDataFinished();
signal in the connection to the slotcloseFtp()
where ftp closes anddeleteLater()
frees the resources. All files downloads well. Thank you. -
Super :)
Seems pretty compact.