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
Caption Servidor
Tedit
Name EditServer
Tlabel
Caption Username
Tedit
Name EditUsername
Tlabel
Caption Password
Tedit
Name EditPassword
Tbutton
Caption Conectar
TNmFTP
Name NmFtp1
TstatusBar
Name Status
* 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
Name StringGrid1
Options.goColSizing TRUE
Options.goRowSelect TRUE
Options.goVertLine FALSE
Options.goHorzLine FALSE
Options.goRangeSelect FALSE
FixedCols 0
DefaultRowHeight 15
GridLineWidth 0
ColCount 4
RowCount 2
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
Caption Download
RadioGRoup
Items ASCII BINÁRIO
ItemIndex 0
Tsavedialog
Name SaveDialog1
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