Читаем QT 4: программирование GUI на С++ полностью

Затем мы выполняем последовательность из четырех команд FTP, используя наш объект QFtp. Вызов url.port(21) возвращает номер порта, указанный в URL, или порт 21, если URL не содержит порта. Поскольку функции login не передаются ни имя пользователи, ни пароль, делается попытка анонимного входа в систему. Второй аргумент функции get задает выходное устройство ввода—вывода.

Команды FTP ставятся в очередь и обрабатываются в цикле обработки событий Qt. Завершение всех команд регистрируется сигналом done(bool) объекта QFtp, который мы подсоединили к слоту ftpDone(bool) в конструкторе.

01 void FtpGet::ftpDone(bool error)

02 {

03 if (error) {

04 cerr << "Error: " << qPrintable(ftp.errorString) << endl;

05 } else {

06 cerr << "File downloaded as " << qPrintable(file.fileName) << endl;

07 }

08 file.close;

09 emit done;

10 }

После выполнения всех команд FTP мы закрываем файл и генерируем сигнал done. Может показаться странным, что мы закрываем файл именно здесь, а не после вызова ftp.close в конце функции getFile, но следует помнить, что команды FTP выполняются асинхронно и их выполнение вполне может быть еще не закончено после возврата управления функцией getFile. Только после генерации объектом QFtp сигнала done мы можем быть уверены, что скачивание файла завершено и теперь можно спокойно закрывать файл.

Класс QFtp поддерживает несколько FTP—команд, включая connectToHost, login, close, list, cd, get, put, remove, mkdir, rmdir и rename. Все эти функции отправляют какую-то команду FTP и возвращают число, идентифицирующее эту команду. Можно также управлять режимом передачи (по умолчанию используется пассивная передача) и типом передачи (двоичный по умолчанию).

Произвольные команды FTP можно выполнять при помощи функции rawCommand. Ниже приводится пример выполнения команды SITE CHMOD:

ftp.rawCommand("SITE CHMOD 755 fortune");

QFtp генерирует сигнал commandStarted(int) в начале выполнения команды и сигнал commandFinished(int, bool) после завершения выполнения команды. Параметр типа int является числом, которое идентифицирует команду. Если мы собираемся отслеживать результаты выполнения отдельных команд, мы можем сохранять эти идентификаторы при постановке команд в очередь. Отслеживание идентификаторов обеспечивает более оперативную обратную связь с пользователем. Например:

01 bool FtpGet::getFile(const QUrl &url)

02 {

03 …

04 connectId = ftp.connectToHost(url.host, url.port(21));

05 loginId = ftp.login;

06 getId = ftp.get(url.path, &file);

07 closeId = ftp.close;

08 return true;

09 }

10 void FtpGet::ftpCommandStarted(int id)

11 {

12 if (id == connectId) {

13 сегг << "Connecting..." << endl;

14 } else if (id == loginId) {

15 cerr << "Logging in..." << endl;

16 …

17 }

Другой способ обеспечения обратной связи заключается в подключении к сигналу stateChanged класса QFtp, который генерируется при всяком изменении состояния соединения (QFtp::Connecting, QFtp::Connected, QFtp::LoggedIn и т.д.).

В большинстве приложений нас интересует только результат исполнения всей последовательности команд, а не каких-то конкретных команд. В таком случае мы можем просто подключить сигнал done(bool), который генерируется всякий раз, когда очередь команд становится пустой.

При возникновении ошибки QFtp автоматически очищает очередь команд. Это означает, что при неудачном подсоединении или входе пользователя в систему оставшиеся в очереди команды никогда не выполнятся. Если мы после возникновения ошибки зададим новые команды с использованием того же объекта QFtp, они будут поставлены в очередь и затем выполнены.

В файл приложения .pro необходимо добавить следующую строку для сборки приложения совместно с библиотекой QtNetwork:

QT += network

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже