segunda-feira, 18 de março de 2013

Genexus FTP - Envio e Recebimento de Arquivos

Nesta matéria irei demonstrar como podemos realizar o envio e o recebimento de arquivos via FTP através de funções do Genexus.

Para atingir este objetivo, vou utilizar, primeiramente para o envio de arquivos, um objeto web panel, onde irei adicionar uma variável blob, capaz de "guardar" um arquivo e, a partir de um botão, realizar o envio deste arquivo para um servidor FTP previamente configurado em uma transação de parâmetros da aplicação.

Após, irei demonstrar como realizar o recebimento deste arquivo salvo no servidor FTP. Com isso podemos até trabalhar com este arquivo, ou então gravá-lo em uma tabela da aplicação.

Funções FTP

O Genexus possui funções FTP pouco conhecidas, ou difundidas... Estas funções não se encontram na biblioteca de funções do software (Menu Insert Function), e mesmo quando digitamos estas funções, ao buscar a tecla de atalho (CTRL + Espaço) elas não são mostradas!

O Genexus disponibiliza 7 funções FTP ao total, estas funções nos permitem desde programar uma conexão a um servidor, quanto excluir arquivos presentes neste servidor. 

Uma função que o genexus não disponibiliza, mas que seria muito importante, é algum método de listar todos os arquivos e pastas presentes no servidor FTP. Para isso devemos utilizar a linguagem ambiente .NET ou Java, mas isso veremos em um outro tópico.

Ao longo dos exemplos irei utilizar e explicar todas estas funções.

Conectando a um Servidor FTP

Bom, para começarmos, primeiro necessitamos de um servidor FTP. Para demonstrar irei imaginar um servidor ftp, seu usuário e senha, isso pois não consegui achar um servidor público que permita realizar o dowload e o upload de arquivos.

As variáveis utilizadas poderão ser recebidas como parâmetros nos objetos.

Vamos então realizar a conexão:

//=====Definindo valores das variáveis=====
&Host = 'ftp.genexus.com'
&Usuario = 'Admin'
&Senha = '123456'

//=====Conexão com o Servidor (Host)=====
Call("GxFtpCon", &Host, &Usuario, &Senha)

//=====Verifica se a conexão foi realizado com sucesso=====
Call("GxFtpError", &Retorno)

//===== Retorno 1 - erro ao conectar=====
if &Retorno = 1
//=====Captura mensagem de erro e exibe na tela=====
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
//=====Retorno 0 - conectado com sucesso=====
msg('Conectado com sucesso')
endif

//=====Realiza Logoff do Servidor FTP=====
Call("GxFtpDis")

Enviando Arquivos a um Servidor FTP

Após realizarmos a conexão a um servidor, a partir de funções do Genexus teremos uma possibilidade de 3 ações a serem tomadas: o envio de arquivos, o recebimento e a exclusão destes.

Vamos começar enviando um arquivo determinado por um usuário da aplicação, através de uma variável blob presente em um objeto web panel.

Para isso, primeiro precisamos desenhar a nossa web panel, de forma bem simples será necessário incluirmos uma variável blob e um botão. Este botão irá chamar a nossa procedure de envio de arquivos, enviando como parâmetro o link do arquivo definido pelo usuário, da seguinte forma:

Event Enter
if &Blob.IsEmpty()
msg('Selecione um arquivo!')
else
ConexaoFTP.Call(&Blob.ToString())
endif
EndEvent

Em nossa procedure, iremos programar o envio do arquivo após a conexão com o servidor FTP. Esta função de envio recebe 3 parâmetros:
  1. Source do arquivo, caminho do arquivo físico, este arquivo deverá estar presente no servidor de hospedagem da aplicação;
  2. Local a ser salvo no servidor FTP. Diretório e nome que será atribuído ao arquivo quando este for enviado ao servidor. Quando apenas o diretório seja informado, o nome permanecerá o mesmo.
  3. Modo de envio, poderá ser ASCII ou Binario. Irei determinar ASCII, mas cada tipo de arquivo possui uma opção ideial. Pesquise para encontrar aquele melhor para o seu caso.
Logo, nossa programação ficará da seguinte forma, em rules:

//=====Caminho físico do arquivo - Varchar(400)=====
parm(in:&SourceArquivo);

Em Source:
&Host = 'ftp.genexus.com'
&Usuario = 'Admin'
&Senha = '123456'
&Diretorio = 'ArquivosEnviados\'

Call("GxFtpCon", &Host, &Usuario, &Senha)
Call("GxFtpError", &Retorno)

if &Retorno = 1
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
msg('Conectado com sucesso')

//=====Realiza o envio de um arquivo para o Servidor=====
// Modo "A" = Ascii "B" = Binario
Call("GxFtpPut", &SourceArquivo, &Diretorio, "A")

//=====Verifica se ocorreu algum erro=====
Call("GxFtpError", &Retorno)
if &Retorno = 1

//=====Captura mensagem de erro e exibe na tela=====
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
msg('Arquivo enviado com sucesso!')
endif
endif

Call("GxFtpDis")

Download e Exclusão de arquivos do Servidor FTP

Bom, por fim vamos visualizar como realizar o download de um arquivo e consequentemente a sua exclusão do servidor FTP.

Assim como a função de Upload, a função de download receberá 3 parâmetros:
  1. Source do arquivo presente no servidor FTP, diretório e nome;
  2. Destino do download, se apenas o diretório for determinado, o arquivo manterá o nome original;
  3. Modo de recebimento, "A" = ASCII, "B" = Binario;

Neste exemplo não precisaremos da nossa web panel, logo, em uma procedure programe os eventos da seguinte forma:

&Host = 'ftp.genexus.com'
&Usuario = 'Admin'
&Senha = '123456'
&SourceArquivo = 'ArquivosEnviados\teste.txt'
&DiretorioDestino = 'C:\Temp\'

Call("GxFtpCon", &Host, &Usuario, &Senha)
Call("GxFtpError", &Retorno)

if &Retorno = 1
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
msg('Conectado com sucesso')

//=====Realiza o download de um arquivo para o Servidor=====
// Modo "A" = Ascii "B" = Binario
Call("GxFtpGet",&SourceArquivo,&DiretorioDestino, "A")

//=====Verifica se ocorreu algum erro=====
Call("GxFtpError", &Retorno)
if &Retorno = 1

//=====Captura mensagem de erro e exibe na tela=====
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
msg('Arquivo recebido com sucesso!')

//=====Realiza a exclusão do arquivo no servidor FTP=====
Call("GxFtpDelete",&SourceArquivo)

//=====Verifica se ocorreu algum erro=====
Call("GxFtpError", &Retorno)
if &Retorno = 1

//=====Captura mensagem de erro e exibe na tela=====
Call("GxFtpStat",&Mensagem)
msg('Erro: '+&Mensagem)
else
msg('Arquivo excluído com sucesso!')
endif
endif
endif

Call("GxFtpDis")

9 comentários:

  1. Muito bom.. Parabens Pelo blog e pela iniciativa em compartilhar conhecimento! Está de Parabens! Continue assim, pois tem centenas de pessoas acessando seu blog e aprendendo muito!
    Abraços
    Tem email pra contato?

    ResponderExcluir
  2. Estou com algumas duvidas! consegui enviar o arquivo, porem, ele NãO envia o meu arquivo teste.txt com o nome original.. o arquivo vai pro host com o nome "BLOB4168943" e conteúdo vazio...
    como posso resolver isso e enviar o arquivo sem erro!?

    ResponderExcluir
    Respostas
    1. Oi Rafael, provavelmente esta recebendo um conteúdo vazio pois as portas de conexão estão fechadas. Você precisa configurar o FTP em Modo Passivo no servidor. Para isso é necessário abrir as portas superiores a 1024 até a 65000.
      Em relação ao nome original, para variáveis do tipo blob desconheço este método, você poderá colocar uma outra variável Varchar, para que o próprio usuário informe o nome do arquivo, e enviar esta variável como parâmetro no método Put do FTP.
      Fiquei curioso em relação a isso, tentarei achar outra forma em linguagem pura ou então em Jquery. Abraço

      Excluir
  3. Obrigado Eduardo, vou tentar aqui...
    A propósito, estou tentando fazer um gerenciamento de arquivo local
    copiar arquivo de um pasta para outra e notificar por email as alterações...
    Usando as common dialog functions
    (gxCopyFile, Selfile, SelDir... etc)

    tem algum tutoria nesse sentido? alguma dica, quais objetos usar, etc
    desde ja agradeço atenção
    Abraços fraternos
    Rafael

    ResponderExcluir
    Respostas
    1. Rafael, se o objetivo for este, você poderá utilizar as variáveis do tipo Directory e File.

      &Directory.Source = "C:\Pasta1\"

      //=====Percorre arquivo por arquivo dentro desta pasta
      For &File in &Directory.GetFiles()
      &File.Copy("Destino")
      Endfor

      Você poderá gravar logs destas copias dentro de um sdt, e ao fim do procedimento enviar por email!

      Abraços

      Excluir
  4. Eduardo,

    ficou uma duvida pequenininha aqui:
    qual objeto devo utilizar nesse processo?
    Work panel? procedure? web panel?
    esse código vai especificamente em Event?

    abraços

    podemos trocar email?
    assim evito fugir do assunto aqui no seu poust de ftp
    rafael@fornax.com.br
    atémais

    ResponderExcluir
  5. Parabéns pelo artigo.
    Existe alguma forma de listar os arquivos que estão em uma determinada pasta do servidor ftp?

    ResponderExcluir
    Respostas
    1. Obrigado, existe sim, porém não através de funções do Genexus. Somente na linguagem crua, Java ou CSharp. Pesquise sobre FtpWebRequest na linguagem de geração da sua KB! Um exemplo em C#: http://www.macoratti.net/12/02/vbn_ftp1.htm

      Excluir
  6. fiz aqui mas na execução diz a seguinte msg (file GxFtpcon.prg does not exist) ele não encontra o prg do programa não sei o que fazer ...

    ResponderExcluir