|
QFtpCompat 1.0.0
Qt6-compatible async FTP client library
|
A Qt6-compatible asynchronous FTP client library.
Drop-in replacement for the QFtp class that was removed from Qt5.
| Dependency | Minimum version |
|---|---|
| Qt | 6.2 |
| CMake | 3.21 |
| C++ standard | 17 |
Qt6::Core and Qt6::Network are propagated automatically via the QFtpCompat::QFtpCompat target – no extra find_package needed in consuming projects.
| Method | Description |
|---|---|
| open(QUrl) | Connect and log in (user/pass from URL). |
| close() | Send QUIT and close the connection. |
| abort() | Abort the current transfer (sends ABOR). |
| resetConnection() | Hard-reset via TCP RST – no QUIT sent. Safe in any state. |
| Method | Description |
|---|---|
| get(url, QIODevice*) | Download to an open device. |
| get(url, QByteArray*) | Download into a byte array. |
| put(url, QByteArray) | Upload from a byte array. |
| put(url, QIODevice*) | Upload from an open device. |
| Method | FTP command | Description |
|---|---|---|
| list(url) | LIST | Directory listing; each entry emitted via listInfo(). |
| mkdir(url) | MKD | Create directory. |
| rmdir(url) | RMD | Remove empty directory. |
| remove(url) | DELE | Delete file. |
| rename(from, to) | RNFR+RNTO | Rename or move. |
| cd(url) | CWD | Change working directory. |
| pwd() | PWD | Current directory (reply via rawCommandReply). |
| rawCommand(cmd) | — | Send any FTP command; reply via rawCommandReply. |
| Signal | When |
|---|---|
| stateChanged(State) | Connection state changed. |
| commandStarted(int id) | A queued command began executing. |
| commandFinished(int id, bool error) | Command completed. |
| done(bool error) | All queued commands finished. |
| listInfo(QFtpCompatDirEntry) | One entry per list() result. |
| dataTransferProgress(qint64, qint64) | Bytes transferred / total. |
| rawCommandReply(int code, QString) | Server reply to rawCommand() / pwd(). |
Only Passive (PASV) is implemented.
Active mode (PORT) is reserved as TransferMode::Active for a future release.
| Value | FTP command | Status |
|---|---|---|
| TransferType::Binary | TYPE I | Fully implemented. |
| TransferType::Ascii | TYPE A | Command sent; CRLF normalisation not yet applied. |
QFtpCompatDirEntry::parseList() recognises three listing formats, tried in order:
The test/ directory contains a standalone Qt console application that exercises every public API method against both a plain FTP server and an Explicit FTPS server.
The certificate is only used locally for testing. Do not commit *.pem files – they are excluded by .gitignore.
Terminal 1 – plain FTP (port 2121):
Terminal 2 – Explicit FTPS (port 2122):
Both servers use ~/ftproot as their root directory and root / root as credentials.
TLS server not available? The test still runs – plain FTP completes normally, then the FTPS section reports [FAIL] OPEN (FTPS) connection refused and exits cleanly without hanging.
| Test case | What is verified |
|---|---|
| open() | Login with credentials in QUrl |
| put(QByteArray) | Upload from memory |
| put(QIODevice*) | Upload 128 KB file with chunked progress |
| mkdir() / rmdir() | Directory lifecycle |
| list() root + subdir | Entry count and file visibility |
| get(QByteArray*) | Download + byte-exact content comparison |
| get(QIODevice*) | Download 128 KB to QFile, size verified |
| rename() | RNFR/RNTO round-trip |
| remove() | Delete all test files |
| pwd() / rawCommand() | Raw command path |
| get() non-existent file | 550 error received as expected |
| Final list() | Server root empty – full cleanup confirmed |
| Test case | What is verified |
|---|---|
| open(..., Explicit) | AUTH TLS → PBSZ 0 → PROT P → login |
| Self-signed certificate | sslErrors → ignoreSslErrors accepted |
| put() over TLS | Upload on encrypted data channel |
| list() | File visible in encrypted directory listing |
| get() over TLS | Download + byte-exact content comparison |
| remove() + final list() | Cleanup confirmed |
The generated HTML is copied to docs/html/ automatically, ready for GitHub Pages (see below).
Requires Doxygen.
Graphviz (dot) is optional but enables class diagrams.
Update the link at the top of this README to match.
MIT – see [LICENSE](LICENSE).