Criando um FTP cliente com o Visual Basic


A Internet não se limita ao protocolo http ou a Web. Quem usa o correio eletrônico (sem ser através de uma daquelas contas gratuitas que normalmente são processadas também através de um browser) sabe bem isso. Para proceder a transferências de arquivos, pode certamente usar-se o browser, o que aliás, hoje em dia, é o normal... Mas há outros processos.  Hoje em dia, há dois protocolos principais para acesso a arquivos na Net ; FTP é um deles, o outro é o HTTP.

O FTP – File Transfer Protocol (protocolo de transferência de arquivos) continua a ser, desde a sua criação nos anos 70,  o principal protocolo utilizado para transferir arquivos entre computadores ligados à Internet. Dos seus serviços, o mais comum é o FTP anônimo, pois este, permite o download de dados e arquivos contidos nos sites sem a necessidade de autenticação.(fornecimento de nome do usuário e senha).

Nota: Existem diversos servidores ftp de acesso anônimo com conteúdo de interesse público.

O FTP também é utilizado de forma personalizada e automática em soluções que trabalham como o EDI (Eletronic Data Interchange), onde Matriz e Filial trocam arquivos de dados com a finalidade de sincronizar seus bancos de dados.
 
O FTP no modo padrão

O protocolo FTP utiliza duas conexões TCP, a primeira é conhecida como “Ftp-controle” que é estabelecida pelo cliente em uma porta TCP de número alto (1025 a 65535) e se comunica com o servidor de FTP em uma porta TCP padrão, número 21. Essa conexão diz ao servidor qual(is) arquivo(s) o cliente deseja e permite a passagem de outras informações de controle (comandos por exemplo). Contudo, quando chega à hora de transferir os dados reais, uma segunda conexão, conhecida como “Ftp-dados” será aberta. Diferente da conexão de controle, essa conexão é aberta pelo servidor na porta TCP 20 e se comunica com o FTP cliente em uma porta TCP que é atribuída dinamicamente e não é privilegiada (o cliente e o servidor negociam a porta como parte da troca de controle

O FTP no modo passivo

O segundo método para a execução do protocolo é o FTP em modo passivo. Esse, consiste em fazer com que o cliente abra a conexão do “Ftp-dados” quando for preciso, e tudo é estabelecido na conexão “Ftp-controle” onde fica estabelecida inclusive a porta TCP que o cliente vai usar contra o servidor. Além de modificar o sentido da conexão “Ftp-dados”, as portas nesse modo são altas tanto no cliente como no servidor; valores que variam entre 1025 a 65535.

Outro aspecto importante que deve ser mencionados aqui é o fato de que as redes, normalmente, se conectam à Internet através de um Gateway, e que esse, dependendo do tipo e concepção, pode fazer com que o FTP seja configurado de forma nada convencional.
 
Nota : Na conexão FTP no modo padrão, a parte
Ftp-dados, traz sérios problemas para a segurança das redes, o motivo é que a conexão no sentido do servidor em uma porta abaixo de 1025 (o default é 20), contra o cliente em uma porta dinâmica, maior que 1024, sem o flag ACK acionado, é considerado pelos administradores de segurança de redes, como acesso indevido e, será simplesmente descartado. Já o modo passivo, é considerado o modo correto de se conectar com FTP.

Existem diversos programas clientes que podem ser usados para realizar uma conexão ftp e oferecem um interface amigável com o usuário. Só para citar um dos mais usados temos o : WS-FTP

Podemos também criar nosso próprio programa de FTP para rodar no cliente usando o Visual Basic. Neste artigo vou mostrar como criar um cliente FTP usando o controle Inet.

Usando FTP

A sintaxe para o FTP é simples, bastando escrever na linha de comando: 
ftp nomehost 

onde nomehost é o nome da máquina em que se encontra o servidor ftp. Por exemplo, 

ftp maquina.rede.br     Ex:  ftp penta.ufrgs.br    ou    ftp 143.54.1.19

Usuário cadastrado

Quando você for usuário cadastrado no servidor FTP que quer acessar, entre normalmente seu login e password

ftp maquina.rede.br 
Connected to maquina.rede.br
220 maquina FTP server ready. 
Name (maquina:user): fulano 
331 Password required for fulano
Password: ******** 
230 User fulano logged in. 
ftp> _ 

A partir daí, utilize os comandos de FTP.

 Ao usar programas com interface gráfica, o uso dos comandos é transparente (ou seja: nesse caso, não é preciso saber os comandos necessários).

 

Usuário "anônimo"

No caso de não ser cadastrado no servidor FTP desejado, entre como usuário "anônimo": 

ftp maquina.rede.br 
Connected to maquina.rede.br
220 maquina FTP server ready. 
Name (maquina:user): anonymous 
331 Guest login ok, send ident as password. 
Password: fulano@meu.provedor.br 
230 Guest login ok, access restrictions apply. 
ftp> _ 

Neste caso, em vez de usar uma senha de acesso, use uma identificação, em geral seu endereço e-mail. As restrições de acesso bloqueiam a entrada do usuário em alguns diretórios, por questões de segurança do sistema.

Nota: O FTP possui dois modos de transferência, o ASCII e o binário. O modo ASCII é utilizado quando queremos transferir arquivos textos simples (sem nenhum efeito do tipo negrito, sublinhado, fonte de letra, etc.). Já o modo binário é utilizado para transferir programas, imagens gráficas, planilhas, som, etc.

O problema é saber quando um arquivo é do tipo ASCII ou do tipo binário, pois se fizermos uma transferência no modo errado, o arquivo ficará corrompido. Por exemplo, se ele for um programa e tentarmos executá-lo, a máquina irá travar.

Principais comandos FTP

Existem muitos comandos ftp; Abaixo uma relação dos principais :

Lembre-se: as frases entre colchetes indicam parâmetros alternativos dos comandos.  

binary 
Ou simplesmente bin. Estabelece como binário o tipo de representação dos arquivos a serem manipulados.

Use este comando sempre que for lidar com arquivos de imagem, documentos formatados, executáveis e arquivos compactados. 
cd diretório_remoto 
Muda o diretório de trabalho na máquina remota. 
cdup 
Muda o diretório de trabalho para o diretório "pai" (superior) do diretório atual. 
lcd [ diretório ] 
Muda o diretório de trabalho na máquina local.
 Se nenhum diretório for especificado, o diretório "home" do usuário é utilizado. 
get arq_remoto [ arq_local ] 
Recupera o arquivo_remoto e o arqmazena na máquina local. Se um nome de arquivo_local não for especificado, é dado o mesmo nome do arquivo na máquina remota. 
mget arquivos_remotos 
Faz um get para cada arquivo remoto cujo nome esteja na lista de arquivos_remotos. 
put arq_local [ arq_remoto ] 
Armazena um arquivo local na máquina remota. Se não for especificado um nome arquivo remoto, ele terá o mesmo nome do arquivo local. 
mput arquivos_locais 
Faz um put para cada arquivo local cujo nome esteja na lista de arquivos_locais 
help [ comando ] 
Ou apenas ?, escreve uma mensagem explicativa sobre o significado do comando.

Quando nenhum comando é especificado, apresenta uma lista de comandos. 
ls [ dir_remoto ] [ arq_local ] 
Dá uma listagem do conteúdo de um diretório da máquina remota. Se não for especificado um diretório remoto, é mostrada a listagem do diretório de trabalho usado.

Se nenhum arquivo local for especificado, a listagem é mostrada na tela. 
dir [ dir_remoto ] [ arq_local ] 
Lista o conteúdo do diretório da máquina remota, colocando o resultado na máquina local.

Se nenhum diretório remoto for especificado, o diretório de trabalho atual na máquina remota será utilizado. 

Se nenhum arquivo na máquina local for especificado para receber a lista do diretório remoto, o resultado é enviado para o terminal. 
!dir [ dir_local ] [ arq_local ] 
Em alguns sistemas ftp, este comando lista o conteúdo de um diretório da máquina local. 
pwd 
Retorna o nome do diretório atual na máquina remota. 
quit 
Termina uma sessão ftp 

Criando seu cliente FTP no Visual Basic

Na figura abaixo esta o projeto que iremos criar no Visual Basic e que pode ser usado para conexão com servidores FTP. A interface é bem simples , como você ja notou. Ela foi construída com os controles relacionados abaixo usando a configuração informada: (A configuração é feita através da janela Properties (selecione o controle e pressione F4 para abrir a janela)

- Exemplo de conexão com o servidor anônimo ftp.pucpr.br

 

Nota: para saber mais sobre o controle Inet leia o artigo : Internet Transfer Control (Inet) – Transferindo arquivos com o VB

Vamos agora ao código do projeto.

1- Este código esta associado ao evento Click do botão  - cmdConecta - Conectar ao Host Remoto . Ele verifica se estamos conectados pela string exibida na propriedades caption e conforme o estado invoca uma das duas rotinas:

Private Sub cmdConecta_Click()
' Verifica a propriedade Caption para desconectar ou conectar
If Left(cmdConecta.Caption, 4) = "&Con" Then
    conectaHost
Else
    desconectaHost
End If
End Sub
 

2- O código da rotina conectaHost é dado a seguir. Esta rotina faz o seguinte :

Private Sub conectaHost()
Dim operacao As String

On Error GoTo connectError

If txtAddress.Text <> "" Then
   itcFTP.URL = txtAddress.Text
   itcFTP.UserName = txtUsername.Text
   itcFTP.Password = txtPassword.Text

   listaDir
   cmdEnvia.Enabled = True
   cmdRecebe.Enabled = True
   cmdMkDir.Enabled = True
   cmdDelete.Enabled = True
   lstRemote.Enabled = True
   cmdConecta.Caption = "D&esconectar do Host Remoto"
Else
   MsgBox "Informe o nome do servidor FTP.", vbCritical
   txtAddress.SetFocus
End If
Exit Sub

connectError:
   MsgBox Err.Description, vbExclamation, "FTP"
End Sub

3- Vou exibir agora o código da rotina desconectaHost . Ela faz o seguinte serviço:

Private Sub desconectaHost()

On Error GoTo trata_erro

Dim operacao As String

itcFTP.Execute , "quit"
operacao = "quit"
executaComando operacao, False
cmdEnvia.Enabled = False
cmdRecebe.Enabled = False
cmdMkDir.Enabled = False
cmdDelete.Enabled = False
lstRemote.Enabled = False
cmdConecta.Caption = "&Conectar ao Host Remoto"
Exit Sub

trata_erro:
      MsgBox "Erro ao efetuar a operacao com : " & txtAddress.Text & vbCrLf & " erro : " & Err.Number

End Sub

A rotina executaComando envia os comandos FTP para o servidor via controle INET. Vejamos o que ela faz:

Private Sub executaComando(ByVal op As String, ByVal ld As Boolean)

On Error GoTo trata_erro

If itcFTP.StillExecuting Then
    itcFTP.Cancel
End If

txtLog.Text = txtLog.Text & "Comando: " & op & vbCrLf

itcFTP.Execute , op
terminaComando

If ld = True Then
    listaDir
    terminaComando
End If
Exit Sub

trata_erro:
   MsgBox "Não foi possivel efetuar operacao com : " & txtAddress.Text & vbCrLf & " erro : " & Err.Number
End Sub

A rotina terminaComando apenas faz o seguinte :

Private Sub terminaComando()
Do While itcFTP.StillExecuting
   DoEvents
   Loop
End Sub

A rotina listaDir tem o seguinte código . Ele exibe os nomes dos arquivos e diretórios no ListBox referente ao Host Remoto.

Private Sub listaDir()
Dim operacao As String
Dim data As Variant, contador As Integer
Dim inicio As Integer, length As Integer

inicio = 1
lstRemote.Clear
operacao = "dir"

executaComando operacao, False

Do
   data = itcFTP.GetChunk(1024, icString)
   DoEvents

   For contador = 1 To Len(data)
      If Mid(data, contador, 1) = Chr(13) Then
          If length > 0 And Mid(data, inicio, length) <> "./" Then
               lstRemote.AddItem Mid(data, inicio, length)
          End If
          inicio = contador + 2
          length = -1
      Else
          length = length + 1
      End If
    Next contador

Loop While LenB(data) > 0

operacao = "pwd"
executaComando operacao, False
lblRemoteDirectory.Caption = itcFTP.GetChunk(1024, icString)

End Sub

Vamos agora ao código dos botões : MkDir , Delete , Envia (->) e Recebe (<-):

1- rotina associado ao botão - MkDir - cria um diretório no hot remoto (pelo menos tenta...)

Private Sub cmdMkDir_Click()
Dim dir As String, operacao As String

dir = InputBox("Informe o nome da pasta", "Cria Diretório")
If dir <> "" Then
operacao = "mkdir " & dir
executaComando operacao, True
End If
End Sub

2- rotina associado ao evento Click do botão - Delete - exclui um arquivo do host remoto .( se der...)

Private Sub cmdDelete_Click()
    
    Dim operacao As String
    Dim nomeArquivo As String
    Dim response As Integer, contador As Integer
    
    response = MsgBox("Confirma a operação ?", vbQuestion + vbYesNo, "Delete")
    If response = vbYes Then
        For contador = 0 To lstRemote.ListCount - 1
            If lstRemote.Selected(contador) = True Then
                nomeArquivo = lstRemote.List(contador)
                ' Verifica se é um diretorio ou arquivo
                If Right(nomeArquivo, 1) = "/" Then
                    operacao = "rmdir " & Left(nomeArquivo, Len(nomeArquivo) - 1)
                Else
                    operacao = "delete " & nomeArquivo
                End If
                executaComando operacao, False
            End If
        Next contador
        listaDir
    End If
End Sub

 

3- rotina associado ao evento Click do botão - Recebe ( <- ) - recebe um arquivo selecionado.

Private Sub cmdRecebe_Click()
    Dim contador As Integer
    Dim operacao As String
    Dim nomeArquivo As String, arquivoSaida As String
    
    For contador = 0 To lstRemote.ListCount - 1
        If lstRemote.Selected(contador) = True Then
            nomeArquivo = lstRemote.List(contador)
            If Len(dirList.Path) > 3 Then
                arquivoSaida = dirList.Path & "\" & nomeArquivo
            Else
                arquivoSaida = dirList.Path & nomeArquivo
            End If
            operacao = "recv " & nomeArquivo & " " & arquivoSaida
            executaComando operacao, False
            lstRemote.Selected(contador) = False
        End If
    Next contador
   filList.Refresh
End Sub

 

4- rotina associado ao evento Click do botão - Envia ( -> ) - envia um arquivo selecionado para o Host.

Private Sub cmdEnvia_Click()
    Dim contador As Integer
    Dim operacao As String
    Dim nomeArquivo As String, arquivoSaida As String
    
    For contador = 0 To filList.ListCount - 1
        If filList.Selected(contador) = True Then
            nomeArquivo = filList.List(contador)
            arquivoSaida = lblRemoteDirectory.Caption & "/" & nomeArquivo
            operacao = "send " & filList.Path & "\" & nomeArquivo & " " & arquivoSaida
            executaComando operacao, False
        End If
    Next contador
    listaDir
    filList.Refresh
End Sub

Durante a tentativa de conexão o status do controle muda ; abaixo o código associado ao evento StateChanged notifica o usuário do estado da conexão.

Private Sub itcFTP_StateChanged(ByVal State As Integer)
    Select Case State
        Case icResolvingHost
            lblStatus.Caption = "Resolvendo Host"
        Case icHostResolved
            lblStatus.Caption = "Host Resolvido"
        Case icConnecting
            lblStatus.Caption = "Conectando ..."
        Case icConnected
            lblStatus.Caption = "Conectado"
        Case icRequesting
            lblStatus.Caption = "Requesitando ..."
        Case icRequestSent
            lblStatus.Caption = "Requesição enviada"
        Case icReceivingResponse
            lblStatus.Caption = "Recebendo ..."
        Case icResponseReceived
            lblStatus.Caption = "Resposta recebida"
        Case icDisconnecting
            lblStatus.Caption = "Desconectando ..."
        Case icDisconnected
            lblStatus.Caption = "Desconectado"
        Case icError
            lblStatus.Caption = itcFTP.ResponseInfo
            txtLog.Text = txtLog.Text & itcFTP.ResponseInfo & vbCrLf
        Case icResponseCompleted
            lblStatus.Caption = "operacao Completa"
            txtLog.Text = txtLog.Text & "operacao Completa" & vbCrLf
    End Select
    txtLog.SelStart = Len(txtLog.Text)
End Sub

 

 

No controle lstRemote (uma caixa de listagem) que exibe os arquivos e pastas do Host, temos o seguinte código associado ao evento Dbl_Click.

 

Private Sub lstRemote_DblClick()
    Dim operacao As String, dir As String
    
    ' Se o item é uma pasta muda para a pasta
    If Right(lstRemote.List(lstRemote.ListIndex), 1) = "/" Then
        dir = lstRemote.List(lstRemote.ListIndex)
        operacao = "cd " & Left(dir, Len(dir) - 1)
        executaComando operacao, True
    End If
End Sub

 

Para os controles DirListBox e DriveListBox temos o seguinte código:

Private Sub dirList_Change()
   filList.Path = dirList.Path
End Sub

Private Sub drvList_Change()
On Error GoTo driveError

dirList.Path = drvList.Drive
Exit Sub
driveError:
MsgBox Err.Description, vbExclamation, "Drive Error"
End Sub

E , no evento Unload do formulário temos :

Private Sub Form_Unload(Cancel As Integer)

On Error GoTo trata_erro

If cmdEnvia.Enabled = True Then
    itcFTP.Execute , "Quit"
End If
Exit Sub

trata_erro:
   MsgBox "Erro na aplicação FTP", vbCritical
End Sub

Pegue o projeto completo aqui: FtpInet.zip ( 5k ) . E bom FTP...
Até o próximo artigo VB...

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti