VB .NET - Descarregando arquivos via FTP


Em meu artigo Cliente FTP com VB - Macoratti.net eu já tratei do assunto de como usar FTP com o Visual Basic e hoje vou mostrar como podemos usar o mesmo recurso no VB .NET.

Na linguagem VB .NET temos suporte a este recurso através da classe FtpWebRequest que implementa um cliente de protocolo FTP.

Para obter uma instância de FtpWebRequest, use o método Create. Você também pode usar a classe WebClient para fazer upload e download de informações de um servidor FTP. Usando qualquer uma dessas abordagens, quando você especificar um recurso de rede que usa o esquema FTP (por exemplo, "ftp://contoso.com") a a classe FtpWebRequest fornece a capacidade de interagir programaticamente com servidores de FTP.

Você deve ter um nome de usuário válido e a senha para o servidor FTP ou o servidor deve permitir logon anônimo.

Você pode especificar as credenciais usadas para conectar ao servidor, definindo a propriedade Credentials ou você pode incluí-los na parte UserInfo da URI passada para o método Create. Se você incluir as informações UserInfo na URI, a propriedade Credentials será definida como uma nova credencial de rede com as informações do nome do usuário e e senha especificados.

Você deve ter acesso aos recursos HTTP (WebPermission) para acessar o recurso FTP de outra forma será lançada uma exceção SecurityException.

Se a propriedade Proxy for definida, seja diretamente ou em um arquivo de configuração, a comunicação com o servidor FTP será feita através do proxy definido. Se for um proxy HTTP somente os comandos DownloadFile, ListDirectory, e ListDirectoryDetails serão suportados.

Em um exemplo bem simples de utilização dos recursos FTP para listar os arquivos de uma pasta do servidor temos que:

1- Primeiro você cria uma instãncia da classe FtpWebRequest e definir o endereço FTP da pasta de onde voce quer listar os arquivos:
Dim fwr As FtpWebRequest = FtpWebRequest.Create(
"ftp://ftp.google.com")

2- A seguir você precisa definir o nome do usuário e a senha para acessar o servidor FTP usando a propriedade Credentials do
FtpWebRequest que é do tipo ICredential e você pode definir para um objeto do tipo NetworkCredential:
fwr.Credentials = New NetworkCredential(“userName”, “password”)

3- Então você precisa especifricar o método da classe que é uma instância do objeto WebRequestMethods:
fwr.Method = WebRequestMethods.Ftp.ListDirectory

4- Após especificar estas propriedades você recebera uma lista de arquivos e pasta e usando um Stream reader poderá exibir o resultado:
Dim sr As New StreamReader(fwr.GetResponse().GetResponseStream())
Dim str As String = sr.ReadLine()
While Not str Is Nothing
   Console.WriteLine(str)
   str = sr.ReadLine()
End While
sr.Close()
sr = Nothing
fwr = Nothing

Resumindo podemos dizer que em uma requisição FTP temos as seguintes tarefas:

* Crição de uma requisição web para uma URL.
* Definição das credenciais de login (username, password).
* Definição das opções e as ações necessárias a executar.
* Upload dos dados necessários (Não utilizado por algumas ações).
* Download dos dados e/ou resultados (não usado por algumas ações).
* Fechamento do pedido (e conexão).

Abaixo temos a indicação do código necessário para cada uma destas tarefas para realizar um download de um arquivo:

        'Valores usado no exemplo
        Const localFile As String = "C:\arquivo.bin"
        Const remoteFile As String = "/pub/servidorftp.bin"
        Const host As String = "ftp://ftp.host.com"
        Const username As String = "usuario"
        Const password As String = "senha"

        '1. Cria uma requisição: deve estar no formato ftp://hostname
        'e não apensa ftp.myhost.com
        Dim URI As String = host & remoteFile
        Dim ftp As System.Net.FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)

        '2. Define as credenciais
        ftp.Credentials = New System.Net.NetworkCredential(username, password)

        '3. Definindo a ação
        ftp.KeepAlive = False
        'definindo uma transferencia binária e não textual
        ftp.UseBinary = True
        'Define a ação (neste caso fazer um downloa de um arquivo)
        ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile

        '4. se voce estiver usando um método que envia um arquivo 
        '5. Obtem a resposta da requisição ftp e do stream associado
        Using response As System.Net.FtpWebResponse = CType(ftp.GetResponse, System.Net.FtpWebResponse)
            Using responseStream As IO.Stream = response.GetResponseStream
                'percorre para ler/escrever o arquivo
                Using fs As New IO.FileStream(localFile, IO.FileMode.Create)
                    Dim buffer(2047) As Byte
                    Dim read As Integer = 0
                    Do
                        read = responseStream.Read(buffer, 0, buffer.Length)
                        fs.Write(buffer, 0, read)
                    Loop Until read = 0 
                    responseStream.Close()
                    fs.Flush()
                    fs.Close()
                End Using
                responseStream.Close()
            End Using
            response.Close()
        End Using
        '6. Fim 
    End Sub

Vejamos agora um exemplo básico para descarregar um arquivo.

Abra o Visual Basic 2010 Express Edition e crie um novo projeto Windows Forms Application com o nome DescarregarArquivoFTP;

No formulário padrão form1.vb inclua os comandos: Label, TextBox e Button conforme o leiaute abaixo:

A seguir defina o seguinte código no formulário:

Imports System
Imports System.Net
Imports System.IO
Imports System.Text

Public Class Form1

       Private Sub descarregarArquivo(ByVal arquivoFTP As String, _
                             ByVal usuario As String, ByVal senha As String, _
                             ByVal dirLocal As String)

        Dim dirFtp As FtpWebRequest = CType(FtpWebRequest.Create(arquivoFTP), FtpWebRequest)

        ' credenciais do usuário
        Dim credenciais As New NetworkCredential(usuario, senha)
        dirFtp.Credentials = credenciais

        ' comando para executar usando a enumeração de WebRequestMethods.Ftp
        dirFtp.Method = WebRequestMethods.Ftp.DownloadFile

        ' Obtem resultado do comando
        Dim reader As New StreamReader(dirFtp.GetResponse().GetResponseStream())

        ' Ler o stream (o conteudo do arquivo)
        Dim resultado As String = reader.ReadToEnd()

        ' Mostrar
        'exibeArquivo(resultado)

        ' Guardar localmente com a extensão .txt
        Dim ficLocal As String = Path.Combine(dirLocal, Path.GetFileName(arquivoFTP) & ".txt")
        Dim sw As New StreamWriter(ficLocal, False, Encoding.Default)
        sw.Write(resultado)
        sw.Close()

        ' Fecha o stream aberto
        reader.Close()
    End Sub

Para usar a rotina acima fazemos assim:

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        descarregarArquivoFTP(txtServidorFTP.Text, txtUsuario.Text, txtSenha.Text, txtArquivo.Text)
    End Sub

Da mesma forma poderíamos definir o código para realizar as operações básicas FTP. Abaixo um exemplo para listar os arquivos de um diretório:

Sub listarFTP(ByVal dir As String, ByVal usuario As String, ByVal senha As String)

        Dim dirFtp As FtpWebRequest = CType(FtpWebRequest.Create(dir), FtpWebRequest)

        ' credenciais
        Dim credenciais As New NetworkCredential(usuario, senha)
        dirFtp.Credentials = credenciais

        'comando a executar
        dirFtp.Method = "LIST"

        'usando a enumeração WebRequestMethods.Ftp
        dirFtp.Method = WebRequestMethods.Ftp.ListDirectoryDetails

        ' Obtem o resultado do comando
        Dim reader As New StreamReader(dirFtp.GetResponse().GetResponseStream())

        ' Ler o stream
        Dim res As String = reader.ReadToEnd()

        ' Mostrar. (falta definir o método)
        'exibir(res)

        ' Fechar o stream aberto.
        reader.Close()
    End Sub

Para enviar um arquivo (upload) podemos definir o código a seguir:

 Public Sub EnviarArquivoFTP(ByVal caminhoArquivoFtp As String, ByVal arquivo As String)
        'Informe o nome servidor ftp ou ip 
        Dim ftphost As String = "127.0.0.1"

        Dim caminhoFTP As String = "ftp://" & ftphost & caminhoArquivoFtp
        Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(caminhoFTP), FtpWebRequest)

        'define as credenciais 
        ftp.Credentials = New NetworkCredential(txtUsuario.Text, txtSenha.Text)
        'define o tipo de ação 
        ftp.KeepAlive = True
        ftp.UseBinary = True
        ftp.Method = WebRequestMethods.Ftp.UploadFile
        'trata o retorno
        Dim fs As FileStream = File.OpenRead(arquivo)
        Dim buffer As Byte() = New Byte(fs.Length - 1) {}
        fs.Read(buffer, 0, buffer.Length)
        fs.Close()
        Dim ftpstream As Stream = ftp.GetRequestStream()
        ftpstream.Write(buffer, 0, buffer.Length)
        ftpstream.Close()
    End Sub

E a sua chamada pode ser feita assim:

 Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        ''EnviarArquivoFTP("/testePasta/testefile.xml", "c:\testefile.xml")
        EnviarArquivoFTP(txtServidorFTP.Text, txtArquivo.Text)
    End Sub

Se você precisar criar um cliente FTP é melhor usar as boas práticas para criar um componente que possa depois ser referenciado em seus projetos.

Existe um arquivo de exemplo da Microsoft onde você encontra um cliente FTP pronto para usar. Pegue aqui: vbftpclient.zip

Pegue o projeto completo aqui: DescarregandoArquivosFTP.zip

 Se pelo nome de Cristo sois vituperados, bem-aventurados sois, porque sobre vós repousa o Espírito da glória, o Espírito de Deus.
 
Que nenhum de vós, entretanto, padeça como homicida, ou ladrão, ou malfeitor, ou como quem se entremete em negócios alheios;

 mas, se padece como cristão, não se envergonhe, antes glorifique a Deus neste nome.
1Pedro 4:14-16

Referências:


José Carlos Macoratti