Artigo Clube Delphi Edição 11 - O objeto TNMFTP

Artigo da Revista Clube Delphi Edição 11.

Esse artigo faz parte da revista Clube Delphi edição 11. Clique aqui para ler todos os artigos desta edição



Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.

O objeto TNMFTP

Compartilhe arquivos na Internet via FTP

 

O protocolo FTP (File Transfer Protocol) é um dos mais utilizados na Web, capacitando diferentes máquinas, com diferentes sistemas, a trocarem arquivos entre si. Sendo um dos primeiros protocolos implementados na Internet, o FTP deu origem a termos como download e upload. 

Os servidores FTP podem ser públicos ou com acesso restrito. Na primeira situação, todos podem se conectar  e executar downloads ou uploads. Na outra hipótese, os usuários precisam estar cadastrados, ou seja, possuir um nome de conexão e uma senha. O servidor pode restringir o acesso a arquivos ou pastas, delegando poderes de leitura ou escrita para cada um. O componente TnmFTP é responsável pela criação de um aplicativo cliente FTP.

 

Nota: O exemplo a seguir cuidará da construção de um aplicativo cliente FTP - mas isto não significa que a funcionalidade deste componente se resume a este tipo  de software - várias situações podem ser solucionadas através deste protocolo. Veja alguns exemplos:

 

· Troca de arquivos de dados entre  aplicativos remotamente separados;

 

· Centralização de arquivos entre vários aplicativos;

 

· Recuperação de arquivos armazenados em outras plataformas, como linux, unix, e outras.

 

Vejamos como construir um aplicativo completo de FTP:

 

1) Efetuando a conexão com o servidor FTP:

 

São necessárias três informações para efetuar a conexão: o endereço ftp, o nome do usuário e a senha. Insira três objetos Edit, três objeto Tlabel, um objeto tbutton e um objeto TstatusBar (palheta Win95/Win32). Configure suas propriedades de acordo com a tabela abaixo:

 

Tlabel

CaptionServidor

Tedit

Name  EditServer

 

Tlabel

CaptionUsername

 

Tedit

NameEditUsername

 

Tlabel

CaptionPassword

 

Tedit

NameEditPassword

 

Tbutton

CaptionConectar

 

TNmFTP

NameNmFtp1

 

TstatusBar

NameStatus

 

* Crie um panel, utilizando a propriedade Panels

 

Selecione o objeto Tbutton e em seu evento OnClick digite:

 

procedure TForm1.Button1Click(Sender: TObject);

begin

 

if NMFTP1.Connected then  begin

 button1.Caption:='Conectar';

NmFtp1.Disconnect;

End

Else begin

NMFTP1.Host := EditServer.Text;

NMFTP1.UserID := Editusername.Text;

NMFTP1.Password := EditPassWord.Text;

Status.Panels[0].Text:='Conectando...';

  nmFtp1.Timeout:=5000; //indica o tempo de espera, em milisegundos

button1.enabled:=False;

try

NMFTP1.Connect;

except

button1.enabled:=true;

Status.Panels[0].Text:='Erro na conexão';

end;

End;

 

end;

 

Selecione o evento OnConnect do objeto TNMFTP, e insira o código abaixo:

 

procedure TForm1.NMFTP1Connect(Sender: TObject);

begin

  Status.Panels[0].text:='Conectado';

  Button1.Enabled:=True;

  Button1.Caption:='Desconectar';

end;

 

O evento OnConnect é gerado quando a conexão é estabelecida com sucesso. Se a conexão falhar, o evento OnConnectionFailed será executado:

 

procedure TForm1.NMFTP1ConnectionFailed(Sender: TObject);

begin

   Status.Panels[0].text:='Conexão falhou.';

  Button1.Enabled:=True;

end;

 

2) Recuperando uma lista de arquivos e pastas contidos no diretório FTP:

 

Agora, o aplicativo deverá exibir a árvore de diretórios e arquivos da pasta FTP. Para incrementar o visual, iremos utilizar o objeto StringGrid encontrado na palheta Additional. Nosso form ficará parecido com a figura a seguir:

 

 

Configure o objeto StringGrid1 de acordo com a tabela abaixo:

 

TstringGrid

 

NameStringGrid1

Options.goColSizingTRUE

Options.goRowSelectTRUE

Options.goVertLineFALSE

Options.goHorzLineFALSE

Options.goRangeSelectFALSE

FixedCols0

DefaultRowHeight15

GridLineWidth0

ColCount4

RowCount2

 

No evento OnShow do formulário, iremos preencher o cabeçalho da grid e definir o tamanho das colunas:

 

procedure TForm1.FormShow(Sender: TObject);

begin

  StringGrid1.ColWidths[0]:=150;

  StringGrid1.ColWidths[1]:=35;

  StringGrid1.ColWidths[2]:=80;

  StringGrid1.ColWidths[3]:=50;

  StringGRid1.Cells[0,0]:='Arquivo';

  StringGRid1.Cells[1,0]:='Tam.';

  StringGRid1.Cells[2,0]:='Data';

  StringGRid1.Cells[3,0]:='Atributos'; 

end;

 

Após efetuada a conexão, o aplicativo deverá ler o diretório do servidor FTP.  Este procedimento é efetuado através do método List. Este método lê a árvore de arquivos do servidor e  armazena na propriedade FtpDirectoryList.

 

Evento OnConnect:

 

procedure TForm1.NMFTP1Connect(Sender: TObject);

begin

  Status.Panels[0].text:='Conectado';

  Button1.Enabled:=True;

  Button1.Caption:='Desconectar';

  Screen.cursor:=crHourGlass;

  NmFtp1.List;

end;

 

Para que as informações sejam inseridas na propriedade FtpDirectoryList, a  propriedade ParseList do objeto TNMFTP1, deverá ser auterada para TRUE.

 

O StringGrid será preenchido no evento OnSuccess:

 

procedure TForm1.NMFTP1Success(Trans_Type: TCmdType);

var

 i:Integer;

begin

  case Trans_Type of

cmdList:begin

StringGrid1.RowCount := NMFTP1.FTPDirectoryList.name.Count+2;

StringGrid1.Cells[0,1]:='..';

StringGrid1.Cells[3,1]:='d';

 

for I := 0 to (NMFTP1.FTPDirectoryList.name.Count - 1) do  begin

   StringGrid1.Cells[0, I+2] := NMFTP1.FTPDirectoryList.name[I];

   StringGrid1.Cells[1, I+2] := NMFTP1.FTPDirectoryList.Size[I];

   StringGrid1.Cells[2, I+2] := NMFTP1.FTPDirectoryList.ModifDate[I];

   StringGrid1.Cells[3, I+2] := NMFTP1.FTPDirectoryList.Attribute[I];

end;

screen.cursor:=CrDefault;

End;

  end; 

end;

 

O evento OnSuccess é chamado sempre que algum comando FTP é completado com sucesso. O parâmetro Trans_Type indica qual a operação que chamou o evento. No nosso caso, devemos nos preocupar com a execução do comando list, para  preencher o objeto StringGrid com as informações.

Repare que  um loop FOR é executado, lendo todas as ocorrências do vetor FtpDirectorylist e preenchendo as informações no objeto Grid:

 

for I := 0 to (NMFTP1.FTPDirectoryList.name.Count - 1) do  begin

   StringGrid1.Cells[0, I+2] := NMFTP1.FTPDirectoryList.name[I];

   StringGrid1.Cells[1, I+2] := NMFTP1.FTPDirectoryList.Size[I];

   StringGrid1.Cells[2, I+2] := NMFTP1.FTPDirectoryList.ModifDate[I];

   StringGrid1.Cells[3, I+2] := NMFTP1.FTPDirectoryList.Attribute[I];

end;

 

 

Caso algum erro aconteça, este será tratado no evento OnFailure:

 

procedure TForm1.NMFTP1Failure(var Handled: Boolean; Trans_Type: TCmdType);

begin

  Screen.Cursor:=CrDefault;

 

  Case Trans_Type of

cmdList:

Status.Panels[0].Text:='Erro durante a leitura do diretório';

 

  end;

end;

 

 

3) Modificando o diretório Corrente

 

É necessário que nosso aplicativo possa alterar o diretório atual, permitindo a navegação na árvore de diretórios. O método que permite a mudança de diretórios  é o ChangeDir. Sua sintaxe segue abaixo:

 

ChangeDir(novo_diretório: String);

 

Neste momento, iremos criar uma interface simples, porém prática: a mudança será feita quando o usuário clicar duas vezes sobre o nome do diretório. Vamos ao evento OnDblClick do objeto StringGrid1:

 

procedure TForm1.StringGrid1DblClick(Sender: TObject);

begin

if nmFtp1.connected then

  if Copy(StringGRid1.Cells[3,StringGRid1.Row],1,1)='d' then  begin

screen.cursor:=crHourGlass;

NMFTP1.ChangeDir(StringGRid1.Cells[0,StringGRid1.Row]);

 End;

end;

 

Os atributos do arquivo selecionado permanecem na coluna 4 do StringGrid. O primeiro passo é descobrir se o objeto selecionado é um diretório. Se for um diretório, a primeira letra do atributo deverá ser 'd'. A comparação é feita na linha:

 

if Copy(StringGRid1.Cells[3,StringGRid1.Row],1,1)='d' then begin

 

O diretório passado como parâmetro para o método ChangeDir será o nome da pasta clicada:

 

NMFTP1.ChangeDir(StringGRid1.Cells[0,StringGRid1.Row]);

 

O último passo é redesenhar a grade para que esta acompanhe a exibição do novo diretório selecionado. Vamos ao evento OnSuccess, do objeto NmFtp:

 

procedure TForm1.NMFTP1Success(Trans_Type: TCmdType);

var

 i:Integer;

begin

  case Trans_Type of

cmdList:

begin

StringGrid1.RowCount := NMFTP1.FTPDirectoryList.name.Count+2;

StringGrid1.Cells[0,1]:='..';

StringGrid1.Cells[3,1]:='d';

for I := 0 to (NMFTP1.FTPDirectoryList.name.Count - 1) do  begin

StringGrid1.Cells[0, I+2] := NMFTP1.FTPDirectoryList.name[I];

StringGrid1.Cells[1, I+2] := NMFTP1.FTPDirectoryList.Size[I];

StringGrid1.Cells[2, I+2] := NMFTP1.FTPDirectoryList.ModifDate[I];

StringGrid1.Cells[3, I+2] := NMFTP1.FTPDirectoryList.Attribute[I];

end;

screen.cursor:=crDefault;

End; 

 

   cmdChangeDir: begin

Status.Panels[0].Text:='Diretório alterado com sucesso.';

mFtp1.List;

End;

 

End;

end;

 

Caso a operação ChangeDir tenha sido efetuada com sucesso, o método list é novamente executado, causando um redesenho no objeto StringGRid.

 

Nota: A primeira linha da grade, contendo o símbolo de dois pontos (..), já estará funcional. Isto porque o símbolo dois pontos é um comando universal para retorno de diretório.

 

Para tratar algum  possível erro, modifique o evento OnFailure, de acordo com a listagem abaixo:

 

procedure TForm1.NMFTP1Failure(var Handled: Boolean; Trans_Type: TCmdType);

begin

  Screen.Cursor := crDefault;

 

  Case Trans_Type of

cmdList:

Status.Panels[0].Text:='Erro durante a leitura do diretório';

 

cmdChangeDir:

Status.Panels[0].Text:='Erro durante a mudança de diretório';

 

  end;

end;

 

4) Efetuando o Download

 

Insira um objeto Tbutton, um objeto SaveDialog e um objeto RadioGroup. Configure suas propriedades como segue abaixo:

 

Tbutton

CaptionDownload

 

RadioGRoup

ItemsASCII BINÁRIO

ItemIndex0

 

Tsavedialog

NameSaveDialog1

Filter*.*|*.*

 

No evento OnClick do botão Download, digite a rotina abaixo:

 

var

LocalFile: String;

 begin

if nmFtp1.Connected then

  if Copy(StringGrid1.Cells[4,StringGRid1.Row],1,1)<>'d' then begin

SaveDialog1.Filename:=StringGrid1.Cells[0,StringGRid1.Row];

 

if saveDialog1.Execute then begin

LocalFile:=SaveDialog1.Filename;

 

case RadioGroup1.ItemIndex of

0: NMFTP1.Mode(MODE_ASCII);

1: NMFTP1.Mode(MODE_BYTE);

end;

 

screen.cursor:=crhourGlass;

NMFTP1.Download(StringGrid1.Cells[0,StringGrid1.Row], Localfile);

screen.cursor:=crDefault;

 

Status.Panels[0].Text:='Download realizado com sucesso';

end;

  end;

Primeiramente, é verificado se o item selecionado é um arquivo. Isto será verdadeiro quando a primeira letra do atributo for diferente de 'd'.

O objeto OpenDialog é executado, e o nome do arquivo de destino é salvo na variável LocalFile. Em seguida, é definido o modo de download do arquivo - se em formato texto ou binário. O usuário poderá fazer a seleção através do objeto TradioGroup:

 

case RadioGroup1.ItemIndex of

0: NMFTP1.Mode(MODE_ASCII);

1: NMFTP1.Mode(MODE_BYTE);

end;

 

O método Mode altera o modo atual de captura do arquivo. E por último o método download é executado. Veja sua sintaxe:

 

DownLoad(Arquivo_de_origem, arquivo_de_destino);

 

O nome do arquivo de origem é o próprio arquivo selecionado na grade. E  o arquivo de destino (local) é o arquivo selecionado no objeto OpenDialog:

 

NMFTP1.Download(StringGrid1.Cells[0,StringGrid1.Row], LocalFile);

 

NOTA: O método de transferência de arquivos indica como as quebras de linha serão representadas. O modo binário indica que não há quebra de linha, e o arquivo será transferido em sua forma original. Já o modo texto leva em consideração os caracteres de CR/LF, interpretando-os da forma necessária.

 

5) Efetuando o UpLoad

 

Inclua um objeto OpenDialog, um objeto botão, e configure sua propriedade Caption para Upload.

 

Em seu evento click, digite:

 

procedure TForm1.Button4Click(Sender: TObject);

var

  Arquivo:sTring;

  i:Integer;

begin

 

if nmFtp1.Connected then

if OpenDialog1.Execute then begin

Arquivo:=SingleFileName(OpenDialog1.Filename);

case RadioGroup1.ItemIndex of

0: NMFTP1.Mode(MODE_ASCII);

1: NMFTP1.Mode(MODE_BYTE);

end;

 

screen.Cursor := CrHourGlass;

NMFTP1.Upload(OpenDialog1.filename, Arquivo);

Status.Panels[0].Text:='Arquivo transferido com sucesso'; End;

end;

end;

 

Repare que o nome do arquivo de destino é extraído do arquivo selecionado no objeto OpenDialog. A propriedade filename deste objeto retorna o nome do arquivo no formato longo, como por exemplo:

 

C:\windows\regedit.exe

 

E, na verdade, precisamos somente do nome puro do arquivo:

 

Regedit.exe

 

A função SingleFileName retorna o nome do arquivo da forma desejada. O código desta função está listado abaixo:

 

function SingleFilename(s:String):String;

var

 cont,

 l:Integer;

Begin

  result:=s;

  l:=-1;

  cont:=Length(s);

  while cont>0 do begin

if Copy(s,cont,1)='\' then begin

l:=cont;

cont:=-1;

end;

cont:=cont-1;

  End;

 

  if l>0 then result:=Copy(s,l+1,length(s)-l);

End;

 

O método Upload é o responsável pela transferência do arquivo ao servidor. Sua sintaxe é:

 

Upload(Arquivo_de_origem, Arquivo_de_Destino)

O objeto TNmFtp, disponibiliza ainda outros recursos, como a criação de diretórios, remoção de arquivos, status de download/upload. O aplicativo de FTP,  que utiliza todos estes recursos,  foi construído sobre a base desta matéria e está disponível, com fontes, no endereço www.clubedelphi.com.br/exemplos/ftp.zip

 

Artigos relacionados