Delphi. Учимся на примерах

Парижский Сергей Михайлович

Глава 18

FTP-клиент

 

 

Постановка задачи

Разработать FTP-клиент. Программа должна соединяться с FTP-cepвером, проходить аутентификацию и предоставлять пользователю возможность работать с файлами, которые находятся на сервере. У пользователя должна быть возможность передавать и получать файлы, создавать и удалять каталоги и т.п. Также пользователь может выполнять свои собственные команды на сервере.

 

Разработка формы

Создайте новый проект Delphi. Приготовьтесь к тому, что форма получится довольно большой (ширина — около 800 пикселей) и будет содержать большое количество разных кнопок и полей ввода. Присвойте ей заголовок FTP-client (свойство Caption) и разместите компоненты согласно табл. 18.1.

Таблица 18.1. Свойства формы FTP-клиента

Компонент Свойство Значение Пояснение
Label1 (категория Standard ) Caption FTP-сервер Надпись метки
Left 56 Отступ слева
Top 16 Отступ сверху
Label2 Caption Имя пользователя Надпись метки
Left 16 Отступ слева
Top 48 Отступ сверху
Label3 Caption Пароль Надпись метки
Left 72 Отступ слева
Top 80 Отступ сверху
Edit1 (категория Standard ) Name ftpserver Новое имя компонента
Text ftp.narod.ru  Адрес FTP-сервера
Left 120 Отступ слева
Top 8 Отступ сверху
Edit2 Name name Новое имя компонента
Text test6001 Имя пользователя
Left 120 Отступ слева
Top 40 Отступ сверху
Edit3 Name pass Новое имя компонента
Left 120 Отступ слева
Top 72 Отступ сверху
Edit4 Name port Новое имя компонента
Text 21 Имя пользователя
Left 120 Отступ слева
Top 104 Отступ сверху
Edit5 Name del Новое имя компонента
Left 512 Отступ слева
Top 8 Отступ сверху
Edit6 Name cd Новое имя компонента
Left 512 Отступ слева
Top 40 Отступ сверху
Edit7 Name cmd Новое имя компонента
Left 512 Отступ слева
Top 72 Отступ сверху
Edit8 Name md Новое имя компонента
Left 512 Отступ слева
Top 104 Отступ сверху
Edit9 Name rd Новое имя компонента
Left 512 Отступ слева
Top 136 Отступ сверху
Edit10 Name download Новое имя компонента
Left 512 Отступ слева
Top 168 Отступ сверху
Button1 (категория Standard ) Caption Подключиться Надпись на кнопке
Left 8 Отступ слева
Top 144 Отступ сверху
Button2 Caption Отключиться Надпись на кнопке
Left 123 Отступ слева
Top 144 Отступ сверху
Button3 Caption Загрузить файл на сервер Надпись на кнопке
Left 512 Отступ слева
Top 200 Отступ сверху
Button4 Caption Удалить Надпись на кнопке
Left 672 Отступ слева
Top 8 Отступ сверху
Button5 Caption Изменить каталог Надпись на кнопке
Left 672 Отступ слева
Top 40 Отступ сверху
Button6 Caption Выполнить команду Надпись на кнопке
Left 672 Отступ слева
Top 72 Отступ сверху
Button7 Caption Создать каталог Надпись на кнопке
Left 672 Отступ слева
Top 104 Отступ сверху
Button8 Caption Удалить каталог Надпись на кнопке
Left 672 Отступ слева
Top 136 Отступ сверху
Button9 Caption Скачать файл Надпись на кнопке
Left 672 Отступ слева
Top 168 Отступ сверху
Memo (категория Standard ) Name status1 Новое имя компонента, предназначенного для отображения состояния соединения
Lines Статус: Текст в поле
Left 264 Отступ слева
Top 8 Отступ сверху
Height 217 Высота
Width 233 РЁРёСЂРёРЅР°
OpenDialog (категория Dialogs ) Name Open1 Новое имя компонента, который будет использоваться для открытия файлов
SaveDialog (категория Dialogs ) Name Save1 Новое имя компонента, который будет использоваться для сохранения файлов
NMFTP (категория FastNet ) Name ftp Новое имя главного компонента программы

Полученная форма должна соответствовать рис. 18.1.

Рис. 18.1. Форма FTP-клиента

 

Разработка программного кода

Обработаем нажатия кнопок соединения и отключения от сервера. Обработчик события OnClick для кнопки Подключиться:

procedure TForm1.Button1Click(sender: TObject);

begin

 ftp.Host:= ftpserver.Text; //ftp-сервер

 ftp.UserID:= name.Text; //логин

 ftp.Password:= pass.Text; // пароль

 ftp.Port:= StrToInt(port.Text) ; //порт для подключения

 //соединяемся с сервером

В if not ftp . Connected then ftp.Connect;

end;

Здесь мы считываем все данные, которые необходимы для соединения с сервером. После этого мы пытаемся соединиться с сервером. Об успешности этой операции можно будет узнать в поле состояния.

Обработаем нажатие кнопки Отключиться:

procedure TForm1.Button2Click(Sender: TObject);

begin

 if ftp . Connected then //если соединен

  ftp.Disconnect; //отключиться от сервера

end;

Если при нажатии кнопки Отключиться установлено соединение с сервером, то мы разрываем его.

Теперь обработаем нажатие кнопок, которые служат для работы с сервером. Обработчик события OnClick для кнопки Удалить:

procedure TForm1.Button4Click(Sender : TObject);

begin

 ftp.Delete(del.text); //удалить файл

end;

Здесь мы удаляем файл, имя которого пользователь ввел в поле рядом с кнопкой.

Обработаем нажатие кнопки Изменить каталог:

procedure TForm1.Button5Click(Sender: TObject);

begin

 ftp.ChangeDir(cd.Text); //изменяем каталог

end;

Устанавливаем текущим тот каталог, который указан в поле cd.

Обработаем нажатие кнопки Выполнить команду:

procedure TForm1.Button6Click(Sender: TObject);

begin

 ftp.DoCommand(cmd.Text); //выполнение команды

end;

При работе с сервером мы предоставляем пользователю возможность работать не только с помощью команд, предусмотренных в интерфейсе, но и выполнять на сервере любые произвольные команды. Для этого у нас есть поле cmd, в котором пользователь вводит команду, и кнопка Выполнить команду, по нажатию которой введенная команда выполняется.

Обработаем нажатие кнопки Создать каталог:

procedure TForm1.Button7Click(Sender: TObject);

begin

 ftp.MakeDirectory(md.Text); //создать каталог

end;

Обработаем нажатие кнопки Удалить каталог:

procedure TForm1.Button8Click(Sender: TObject);

begin

 ftp.RemoveDir(rd.Text); //удалить каталог

end;

Обработаем нажатие кнопки Скачать файл:

procedure TForm1.Button9Click(Sender: TObject);

begin

 //открытие диалогового окна сохранения файла

В if Save1.Execute

 then //скачиваем указанный файл

В  ftp.Download(download.Text, save1.FileName)

 else ShowMessage('File not saved!' ); {если пользователь отказался сохранять файл}

end;

Сначала мы предлагаем пользователю указать имя и путь размещения полученного файла. Затем мы загружаем файл и размещаем его по указанному пути.

Наконец, обработаем нажатие кнопки Загрузить файл на сервер:

procedure TForm1.Button3Click(Sender: TObject);

var

В i: integer;

 FName, temp: string; //для получения имени файла

begin

 if not Open1.Execute then ShowMessage('Файл не выбран!')

В else begin

 //очищаем переменные, которые содержат имя файла

В temp:= '';

В FName:= '';

 //получаем имя файла

В for i: = Length(Open1.FileName) downto 1 do

В begin

В  if Open1.FileName[i] = '\' then break;

В  temp:= temp+ Open1.FileName[i];

В end;

В for i:=length(temp) downto 1 do

В  fname:= fname + temp[i];

  ftp.Upload(Open1.FileName, FName) ; //загружаем файл

В end;

end;

Здесь мы сначала просим пользователя выбрать файл, который он хочет передать на сервер. Затем узнаем имя выбранного файла и загружаем его на сервер с таким же именем.

В общем, наш ftp-клиент уже полностью работоспособен и выполняет все необходимые функции. Единственное, что осталось сделать, — реализовать извещение пользователя о протекании всех операций и обо всех ошибках. Для этого следует создать несколько обработчиков событий компонента ftp.

Событие в случае возникновения ошибки при проверке имени и пароля — OnAuthеntiсatiоnFailed:

procedure TForm1.ftpAuthenticationFailed(var Handled: Boolean);

begin

 status1.Lines.Add('Неверное имя или пароль');

end;

Событие при подключении — OnConnect:

procedure TForm1.ftpConnect(Sender:tobject);

begin

 status1.Lines.Add('Подключено ');

 //локальный ip-адрес

 status1Lines.Add('IP клиента: ' + ftp.LocalIP) ;

 //удаленный ip-адрес

 status1Lines.Add('IPсервера: ' + ftp.RemoteIP);

end;

Событие в случае возникновения ошибки при подключении — OnConnectionFailed:

procedure TForm1.ftpConnectionFailed(Sender: TObject);

begin

 status1.Lines.Add('He удалось подключиться к серверу');

end;

Событие при отключении от сервера — OnDisconnect:

procedure TForm1.ftpDisconnect(Sender: TObject);

begin

 status1.Lines.Add('Отключено');

end;

Событие в случае возникновения некоторой ошибки — OnError:

procedure TForml.ftpError(Sender: TComponent; Errno: Word; Errmsg: String);

begin

 status1.Lines.Add('Ошибка: ' + errmsg);

end;

Событие в случае возникновения ошибки при подключении к серверу — OnInvaIidHost:

procedure TForm1.ftpInvalidHost(var Handled: Boolean);

begin

 status1.Lines.Add('Ошибка при подключении к серверу');

end;

Событие при изменении состояния — OnStatus:

procedure TForm1.ftpStatus(Sender: TComponent; Status: String);

begin

В status1.Lines.Add(Status);

end;

Событие при успешном выполнении операции — OnSuccess:

procedure TForm1.ftpSuccess(Trans_Type: TCmdType);

begin

 status1.Lines.Add('Успешно');

end;

Событие начала передачи данных — OnTransactionStart:

procedure TForm1.ftpTransactionStart(Sender: TObject);

begin

 status1.Lines.Add('Начало передачи данных');

end;

Событие завершения передачи данных — OnTransactionStop :

procedure TForm1.ftpTransactionStop(Sender: TObject);

begin

 statusl.Lines.Add('Конец передачи данных');

end;

Теперь программа полностью готова к использованию. Если у вас нет собственного Web-сайта, то для тестирования FTP-клиента можете зарегистрировать сайт на бесплатном хостинге.

 

Полный исходный код модуля

Полный код программного модуля FTP-клиента представлен в листинге 18.1.

Листинг 18.1. Программный модуль FTP-клиента

unit Unit1;

interface

uses

В Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, NMFtp, StdCtrls, Psock;

type

В TForm1 = class(TForm)

В ftp: TNMFTP;

В ftpserver: TEdit;

В Label1: TLabel;

В Label2: TLabel;

В name: TEdit;

В Label3: TLabel;

В pass: TEdit;

В Label4: TLabel;

В port: TEdit;

В Button1: TButton;

В Button2: TButton;

В status1: TMemo;

В Button3: TButton;

В Open1: TOpenDialog;

В Button4: TButton;

В del: TEdit;

В Button5: TButton;

В cd: TEdit;

В cmd: TEdit;

В Button6: TButton;

В md: TEdit;

В Button7: TButton;

В rd: TEdit;

В Button8: TButton;

В download: TEdit;

В Button9: TButton;

В Save1: TSaveDialog;

В procedure Button1Click(Sender: TObject);

В procedure ftpStatus(Sender: TComponent; Status: String);

В procedure ftpError(Sender: TComponent; Errno: Word; Errmsg : String);

В procedure ftpDisconnect(Sender: TObject);

В procedure ftpConnect(Sender: TObject);

В procedure ftpConnectionFailed(Sender: TObject);

В procedure ftpInvalidHost(var Handled: Boolean);

В procedure ftpSuccess(Trans_Type: TCmdType);

В procedure ftpTransactionStart(Sender: TObject);

В procedure ftpTransactionStop(Sender: TObject);

В procedure ftpAuthenticationFailed(var Handled: Boolean);

В procedure Button2Click(Sender: TObject);

В procedure Button3Click(Sender: TObject);

В procedure FormDestroy(Sender: TObject);

В procedure Button5Click(Sender: TObject);

В procedure Button4Click(Sender: TObject);

В procedure Button6Click(Sender: TObject);

В procedure Button7Click(Sender: TObject);

В procedure Button8Click(Sender: TObject);

В procedure Button9Click(Sender: TObject);

private

В { Private declarations }

public

В { Public declarations }

end;

var

В Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(sender: TObject);

begin

 ftp.Host:= ftpserver.Text; //ftp-сервер

 ftp.UserID:= name.Text;//логин

 ftp.Password:= pass.Text;// пароль

 ftp.Port:= StrToInt(port.Text); //порт для подключения

 //соединяемся с сервером

В if not ftp.Connected then ftp.Connect;

end;

procedure TForm1.ftpStatus(Sender: TComponent; Status: String);

begin

В status1.Lines.Add(Status);

end;

procedure TForml.ftpError(Sender: TComponent; Errno: Word; Errmsg: String);

begin

 status1.Lines.Add('Ошибка: ' + errmsg);

end;

procedure TForm1.ftpDisconnect(Sender: TObject);

begin

 status1.Lines.Add('Отключено');

end;

procedure TForm1.ftpConnect(Sender:tobject);

begin

 status1.Lines.Add('Подключено');

 //локальный ip-адрес

 status1Lines.Add('IP клиента: ' + ftp.LocalIP);

 //удаленный ip-адрес

 status1Lines.Add('IPсервера: ' + ftp.RemoteIP);

end;

procedure TForm1.ftpConnectionFailed(Sender: TObject);

begin

 status1.Lines.Add('He удалось подключиться к серверу');

end;

procedure TForm1.ftpInvalidHost(var Handled: Boolean);

begin

 status1.Lines.Add('Ошибка при подключении к серверу');

end;

procedure TForm1.ftpSuccess(Trans_Type: TCmdType);

begin

 status1.Lines.Add('Успешно');

end;

procedure TForm1.ftpTransactionStart(Sender: TObject);

begin

 status1.Lines.Add('Начало передачи данных');

end;

procedure TForm1.ftpTransactionStop(Sender: TObject);

begin

 statusl.Lines.Add('Конец передачи данных');

end;

procedure TForm1.ftpAuthenticationFailed(var Handled: Boolean);

begin

 status1.Lines.Add('Неверное имя или пароль');

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

 if ftp.Connected then//если соединен

  ftp.Disconnect;//отключиться от сервера

end;

procedure TForm1.Button3Click(Sender: TObject);

var

В i: integer;

 FName, temp: string; //для получения имени файла

begin

 if not Open1.Execute then ShowMessage('Файл не выбран!')

В else begin

 //очищаем переменные, которые содержат имя файла

В temp:= '';

В FName:= '';

 //получаем имя файла

В for i: = Length(Open1.FileName) downto 1 do

В begin

В  if Open1.FileName[i] = '\' then break;

В  temp:= temp+ Open1.FileName[i];

В end;

В for i:=length(temp) downto 1 do

В  fname:= fname + temp[i];

  ftp.Upload(Open1.FileName, FName); //загружаем файл

В end;

end;

procedure TForm1.FormDestroy(Sender: TObject) ;

begin

В if ftp.Connected then ftp.Disconnect;

end;

procedure TForm1.Button5Click(Sender: TObject);

begin

 ftp.ChangeDir(cd.Text); //изменяем каталог

end;

procedure TForm1.Button4Click(Sender : TObject);

begin

 ftp.Delete(del.text); //удалить файл

end;

procedure TForm1.Button6Click(Sender: TObject);

begin

 ftp.DoCommand(cmd.Text); //выполнение команды

end;

procedure TForm1.Button7Click(Sender: TObject);

begin

 ftp.MakeDirectory(md.Text); //создать каталог

end;

procedure TForm1.Button8Click(Sender: TObject);

begin

 ftp.RemoveDir(rd.Text); //удалить каталог

end;

procedure TForm1.Button9Click(Sender: TObject);

begin

 //открытие диалогового окна сохранения файла

В if Save1.Execute

 then //скачиваем указанный файл

В  ftp.Download(download.Text, save1.FileName)

 else ShowMessage('File not saved!'); {если пользователь отказался сохранять файл}

end;

end.

⊚ Р’СЃРµ файлы проекта Рё исполняемый файл рассмотренной программы находятся РЅР° прилагаемом Рє РєРЅРёРіРµ компакт-РґРёСЃРєРµ РІ папке Chapter_18.