C# - Enviando arquivos para o servidor via FTP (FtpWebRequest)


Hoje vou mostrar como podemos usar a classe FtpWebRequest para enviar arquivos para um servidor.

A classe FtpWebRequest implementa um cliente FTP - File Transfer Protocol e permite criar via código conexões com servidores FTP para transferir arquivos.

Para obter uma instância desta classe usamos o método Create:

FtpWebRequest.Create(new Uri(txtDominioFTP.Text)); // FtpWebRequest.Create(txtDominioFtp.Text)

Nota: Você também pode usar a classe WebClient para enviar e baixar informações de um servidor FTP

Usando qualquer uma dessas abordagens quando você especificar o seu recurso de rede que usa o esquema FTP (por exemplo ftp://macoratti.net) a classe FtpWebRequest permite interagir com servidores FTP via código.

A URI informada pode ser relativa ou absoluta:

Você tem que ter um nome de usuário e senha válidos para o servidor ou o servidor deve permitir o login anônimo. As credenciais usadas para se conectar com o servidor podem ser definidas usando a propriedade Credentials ou você pode incluí-las na parte UserInfo da URI passada para o método Create; neste caso a propriedade Credentials é definida para uma nova credencial com a informação do usuário e senha.

Você tem que ter permissão para acessar o recurso FTP ou uma exceção do tipo SecurityException será lançada.

Ao usar FtpWebRequest para enviar um arquivo para um servidor você precisa escrever o conteúdo do arquivo para a requisição stream obtida pela chamada do método GetRequestStream ou pela sua contraparte assíncrona BeginGetRequestStream e EndGetRequestStream. Você tem que escrever para o stream e fechar o stream antes de enviar a requisição.

As requisições são enviadas ao servidor pelo método GeResponse ou BeginGetResponse/EndGetResponse. Quando a operação terminar um objeto FtpWebResponse será retornado, sendo que este objeto fornece o status da operação.

A fazer o download de um arquivo de um servidor FTP, se o comando foi executado com sucesso, o conteúdo do arquivo requisitado estará disponível no stream do objeto da resposta. Este stream pode ser acessado chamando o método GetResponseStream.

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

Somente o download de conteúdo binário é armazenado em cache ou seja o conteúdo recebido pelo comando DownloadFile com a propriedade UseBinary definida como true.

Enviando arquivos para o servidor com FtpWebRequest

Abra o Visual Studio 2012 Express for desktop e clique em New Project;

Selecione a linguagem Visual C# e o template Windows -> Windows Forms Application informando o nome EnviandoArquvosWeb;

No formulário padrão form1.cs inclua os seguintes controles a partir da ToolBox:

Disponha os controles conforme o leiaute da figura abaixo:

Agora vamos definir os namespaces usados no formulário que permitem acessar as classes usadas no projeto :

using System;
using System.IO;
using System.Net;
using System.Windows.Forms;

Agora no evento Click do botão de comando inclua o seguinte código:

private void btnEnviarArquivo_Click(object sender, EventArgs e)
{
     EnviarArquivo();
}

O código da rotina EnviarArquivo() segue abaixo:

 private void EnviarArquivo()
        {
            FtpWebRequest ftpRequest;
            FtpWebResponse ftpResponse;
            try
            {
                //define os requesitos para se conectar com o servidor
                ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(txtDominioFTP.Text));
                ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
                ftpRequest.Proxy = null;
                ftpRequest.UseBinary = true;
                ftpRequest.Credentials = new NetworkCredential("Usuario", "Senha");

                //Seleção do arquivo a ser enviado
                FileInfo arquivo = new FileInfo(txtArquivo.Text);
                byte[] fileContents = new byte[arquivo.Length];

                using (FileStream fr = arquivo.OpenRead()) 
                {
                    fr.Read(fileContents, 0, Convert.ToInt32(arquivo.Length));
                }

                using (Stream writer = ftpRequest.GetRequestStream())
                {
                    writer.Write(fileContents, 0, fileContents.Length);
                }

                //obtem o FtpWebResponse da operação de upload
                ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
                MessageBox.Show(ftpResponse.StatusDescription);
            }
            catch (WebException webex)
            {
                MessageBox.Show(webex.ToString());
            }

O exemplo acima funciona mas tem muitos problemas e pode te dar muita dor de cabeça se você resolver apenas copiar e colar o código em seu projeto e usá-lo como esta.

Para minimizar os problemas que tal criar uma classe para enviar arquivos e tratar corretamente as possíveis exceções que poderão ocorrer durante o processo ?

Nota: A implementação da classe FtpWebRequest e suas correlatas na plataforma .NET deixa a desejar justamente por não tratar de forma adequada os comportamentos envolvidos na operação de envio e baixa de arquivos.

Vamos agora criar um exemplo um pouco mais completo realizando tarefas como enviar, baixar, deletar, criar e listar arquivos e diretórios no servidor FTP.

Abra o Visual Studio 2012 Express for desktop e clique em New Project;

Selecione a linguagem Visual C# e o template Windows Forms Application informando o nome Ftp_Net;

A seguir vamos utilizar os controles : Label, TextBox, Button,ListBox e OpenFileDialog(via código) para criar uma interface com o leiaute definido conforme a figura a seguir:

Nesta interface definimos o IP do servidor, Usuario e senha e realizamos as operações FTP mais comuns no servidor.

No exemplo eu estou usando os métodos da classe FtpWebRequest para realizar as operações. Abaixo a tabela com os métodos da desta classe:

Nome Descrição
Abort Termina uma operação assíncrona FTP. (Substitui WebRequest.Abort.)
BeginGetRequestStream Começa assincronamente abrindo o fluxo de conteúdo de uma solicitação para gravação. (Substitui WebRequest.BeginGetRequestStream(AsyncCallback, Object).)
BeginGetResponse Começa enviando uma solicitação e recebendo uma resposta de um servidor FTP de forma assíncrona. (Substitui WebRequest.BeginGetResponse(AsyncCallback, Object).)
CreateObjRef Cria um objeto que contém todas as informações relevantes necessárias para gerar um proxy usado para se comunicar com um objeto remoto. (Herdado de MarshalByRefObject.)
EndGetRequestStream Termina uma operação assíncrona pendente iniciada com o BeginGetRequestStream. (Substitui WebRequest.EndGetRequestStream(IAsyncResult).)
EndGetResponse Termina uma operação assíncrona pendente iniciada com o BeginGetResponse. (Substitui WebRequest.EndGetResponse(IAsyncResult).)
Equals(Object) Verifica se o objeto especificado é igual ao objeto atual. (Herdado de Object.)
GetHashCode Serve como uma função hash para um tipo específico. (Herdado de Object.)
GetLifetimeService Recupera o objeto de serviço vida útil atual que controla a diretiva de vida útil para esta instância. (Herdado de MarshalByRefObject.)
GetRequestStream Recupera o fluxo usado para carregar dados para um servidor FTP. (Substitui WebRequest.GetRequestStream.)
GetRequestStreamAsync Quando substituído em uma classe descendente, retorna Stream para gravar dados para o recurso de Internet como uma operação assíncrona. (Herdado de WebRequest.)
GetResponse Retorna a resposta do servidor FTP. (Substitui WebRequest.GetResponse.)
GetResponseAsync Quando substituído em uma classe, descendente retorna uma resposta a uma solicitação de Internet como uma operação assíncrona. (Herdado de WebRequest.)
GetType Obtém o Type da instância atual. (Herdado de Object.)
InitializeLifetimeService Obtém um objeto de serviço de tempo de vida para controlar a diretiva vida útil para esta instância. (Herdado de MarshalByRefObject.)
ToString Retorna uma string que representa o objeto atual. (Herdado de Object.)

Pegue o projeto completo aqui: FTP_Net_CShsarp.zip

João 4:13 Replicou-lhe Jesus: Todo o que beber desta água tornará a ter sede;

João 4:14 mas aquele que beber da água que eu lhe der nunca terá sede; pelo contrário, a água que eu lhe der se fará nele uma fonte de água que jorre para a vida eterna.

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti