[Library] QFtpCompat – async FTP client for Qt6
-
Hi all,
while migrating a Qt5 project to Qt6 I ran into the problem –
QFtpis gone andQNetworkAccessManagerapparently doesn't do FTP anymore. I needed to talk to an embedded PLC over FTP and couldn't find anything that was CMake-ready and covered the commands I needed, so I ended up writing my own.The API is queue-based and signal-driven like the old
QFtp, but it's not a drop-in replacement – URLs are used instead of separate host/port parameters, and credentials are passed viaQUrlrather than a dedicated login call.auto *ftp = new QFtpCompat(this); connect(ftp, &QFtpCompat::commandFinished, this, [ftp](int, bool error) { if (error) qWarning() << ftp->errorString(); }); connect(ftp, &QFtpCompat::listInfo, this, [](const QFtpCompatDirEntry &e) { qDebug() << e.name() << e.size(); }); ftp->open(QUrl("ftp://user:pass@192.168.1.1/")); ftp->list(QUrl("ftp://192.168.1.1/data/")); QByteArray buf; ftp->get(QUrl("ftp://192.168.1.1/data/config.cfg"), &buf); ftp->put(QUrl("ftp://192.168.1.1/data/config.cfg"), buf);Explicit FTPS (AUTH TLS) and Implicit FTPS are supported as well:
ftp->open(QUrl("ftps://192.168.1.1/"), QFtpCompat::EncryptionMode::Explicit); connect(ftp, &QFtpCompat::sslErrors, ftp, &QFtpCompat::ignoreSslErrors);Posting this as-is – it works for my use case and has a small integration test suite, but hasn't seen much use beyond that. Feedback and PRs welcome.
-
J J.Hilk marked this topic as a regular topic on
-
Hi all,
while migrating a Qt5 project to Qt6 I ran into the problem –
QFtpis gone andQNetworkAccessManagerapparently doesn't do FTP anymore. I needed to talk to an embedded PLC over FTP and couldn't find anything that was CMake-ready and covered the commands I needed, so I ended up writing my own.The API is queue-based and signal-driven like the old
QFtp, but it's not a drop-in replacement – URLs are used instead of separate host/port parameters, and credentials are passed viaQUrlrather than a dedicated login call.auto *ftp = new QFtpCompat(this); connect(ftp, &QFtpCompat::commandFinished, this, [ftp](int, bool error) { if (error) qWarning() << ftp->errorString(); }); connect(ftp, &QFtpCompat::listInfo, this, [](const QFtpCompatDirEntry &e) { qDebug() << e.name() << e.size(); }); ftp->open(QUrl("ftp://user:pass@192.168.1.1/")); ftp->list(QUrl("ftp://192.168.1.1/data/")); QByteArray buf; ftp->get(QUrl("ftp://192.168.1.1/data/config.cfg"), &buf); ftp->put(QUrl("ftp://192.168.1.1/data/config.cfg"), buf);Explicit FTPS (AUTH TLS) and Implicit FTPS are supported as well:
ftp->open(QUrl("ftps://192.168.1.1/"), QFtpCompat::EncryptionMode::Explicit); connect(ftp, &QFtpCompat::sslErrors, ftp, &QFtpCompat::ignoreSslErrors);Posting this as-is – it works for my use case and has a small integration test suite, but hasn't seen much use beyond that. Feedback and PRs welcome.
@J.Hilk
Hi there. Excellent stuff for the community, thank you.I had a brief look through https://github.com/DeiVadder/QFtpCompat text, and some of the code.
If I were to use FTP again --- as I did years ago --- I would "miss" these features:
NLSTcommand. Clients may map this to aDIRcommand rather thanLIST, IIRC.- ASCII mode states "Command sent; CRLF normalisation not yet applied". If that means it does not do LF<->CR-LF translation.
- Active rather than just Passive mode.
Just noting these. Quite understand if you want to stop at what you have now. :)
-
@J.Hilk
Hi there. Excellent stuff for the community, thank you.I had a brief look through https://github.com/DeiVadder/QFtpCompat text, and some of the code.
If I were to use FTP again --- as I did years ago --- I would "miss" these features:
NLSTcommand. Clients may map this to aDIRcommand rather thanLIST, IIRC.- ASCII mode states "Command sent; CRLF normalisation not yet applied". If that means it does not do LF<->CR-LF translation.
- Active rather than just Passive mode.
Just noting these. Quite understand if you want to stop at what you have now. :)
Like I said, this is currently just the bare minimum viable project for my port 😄
Feel free to contribute if you'd like ^^
Otherwise, development will probably continue once I have a bit more free time again.Any help, feedback, or pull requests are always appreciated!