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

05 QFile *file = new QFile(currentLocalDir + "/"

06 + urlInfo.name);

07 if (!file->open(QIODevice::WriteOnly)) {

08 cerr << "Warning: Cannot open file << qPrintable(

09 QDir::convertSeparators(file->fileName))

10 << endl;

11 return;

12 }

13 ftp.get(urlInfo.name, file);

14 openedFiles.append(file);

15 }

16 } else if (urlInfo.isDir && !urlInfo.isSymLink) {

17 pendingDirs.append(currentDir + "/" + urlInfo.name);

18 }

19 }

Параметр urlInfo слота ftpListInfo содержит информацию о файле в сети. Если это обычный файл (не каталог) и его можно считывать, мы вызываем функцию get для его загрузки. Объект QFile, используемый для загрузки файла, создается с помощью оператора new, и указатель на него хранится в списке openedFiles.

Если содержащиеся в QUrlInfo сведения об удаленном каталоге говорят, что он не является символической связью, этот каталог добавляется к списку pendingDirs. Мы пропускаем символические связи, поскольку они легко могут привести к бесконечной рекурсии.

01 void Spider::ftpDone(bool error)

02 {

03 if (error) {

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

05 } else {

06 cout << "Downloaded " << qPrintable(currentDir) << " to "

07 << qPrintable(QDir::convertSeparators(

08 QDir(currentLocalDir).canonicalPath));

09 }

10 qDeleteAll(openedFiles);

11 openedFiles.clear;

12 processNextDirectory;

13 }

Слот ftpDone вызывается после завершения всех команд FTP или при возникновении ошибки. Мы удаляем объекты QFile для предотвращения утечек памяти, а также для закрытия всех файлов. Наконец, мы вызываем функцию processNextDirectory. Если какие-нибудь каталоги остались, весь процесс повторяется для следующего каталога в списке; в противном случае скачивание файлов прекращается и генерируется сигнал done.

Если ошибок нет, последовательность команд FTP и сигналов будет такой:

connectToHost(host, port)

login

cd(directory_1)

list

emit listInfo(file_1_1)

get(file_1_1)

emit listInfo(file_1_2)

get(file_1_2)

emit done

cd(directory_N)

list

emit listInfo(file_N_1)

get(file_N_1)

emit listInfo(file_N_2)

get(file_N_2)

emit done

Если файл фактически оказывается каталогом, он добавляется в список pendingDirs и, когда завершается скачивание последнего файла, полученного текущей командой list, выдается новая команда cd, за которой следует новая команда list для следующего каталога, ожидающего обработки, и весь процесс повторяется для нового каталога. Скачиваются новые файлы, и в список pendingDirs добавляются новые каталоги до тех пор, пока не будут скачаны все файлы из всех каталогов и список pendingDirs в результате не станет пустым.

Если возникнет сетевая ошибка при загрузке пятого файла, скажем, из двадцати файлов в каталоге, остальные файлы не будут скачаны. Если бы мы захотели скачать как можно больше файлов, то один из способов заключается в выполнении по одной операции GET и ожидании сигнала done(bool) перед выполнением новой операции GET. В функции listInfo мы бы просто добавили имя файла в конец списка QStringList вместо немедленного вызова get, а в слоте done(bool) мы бы вызывали функцию get для следующего загружаемого файла из списка QStringList. Последовательность команд выглядела бы так:

connectToHost(host, port)

login

cd(directory_1)

list

cd(directory_N)

list

emit listInfo(file_1_1)

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