rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua...

24

Transcript of rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua...

Page 1: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.
Page 2: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Caro leitor,

Primeiramente gostaria de desejar um ótimo carnaval e que este mês de Fevereiro seja repleto de felicidade.

Nosso colunista Hamden Vogel redigiu o artigo “THVDataSet – DataSet baseado em Memória”, o qual

implementou rotinas práticas e velozes através do componente THVDataSet. Este componente é um descendente de

“TMemoryStream”, que permite armazenamento temporário de grandes quantidades de dados. Já nosso colaborador

Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Com o avanço das aplicações web voltadas para smartphones as conhecidas como “Single Page Applications” se tornaram

cada dia mais comum. Essas aplicações são nada mais que uma página HTML que carrega o conteúdo sem que a página

seja recarregada dando assim a impressão de que o usuário está usando uma aplicação nativa e não navegando em um

site. O colunista Thiago C. Montebugnoli continua abordando temas voltados para a plataforma .Net junto com a

linguagem C#. O primeiro artigo ele finaliza a série de artigos sobre FTP de Arquivos, sendo que neste ele orienta e

desenvolve um exemplo prático de como deveremos efetuar o Download de Arquivos através de um servidor FTP. Já no

artigo “Linguagem C# - Utilizando o BackgroundWorker” ele nos ensina a trabalhar com este componente presente e

muito utilizado em Windows Forms, uma alternativa para quem precisa implementar o uso de Threads.

Desejo a todos uma boa leitura!

Marcos César Silva

Diretor Técnico

Editorial

Page 3: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Linguagem C# - Utilizando o BackgroundWorker

Uma das razões para fazermos o uso de “Threads” é quando desenvolvemos alguma rotina e encontramos uma

certa “demora” na execução de determinada tarefa. Podemos destacar alguns exemplos como: consulta em banco de

dados, acesso a um determinado serviço, leitura de qualquer tipo de arquivo, e consequentemente, esta tela fica

“travada” até que a tarefa se finalize, impedindo que o usuário acesse qualquer outro tipo de rotina. Para isto, existe o

componente “BackgroundWorker”, presente na linguagem C# junto com a plataforma Windows Forms. Neste artigo

iremos descrever algumas de suas principais funcionalidades.

Criando o exemplo

A origem do “BackgroundWorker” vem do namespace “System.ComponentModel” e o seu uso é muito fácil e

intuitivo, bastando arrastá-lo no formulário para visualizarmos os eventos e principais propriedades.

Ver Imagem 01.

Figura 01: Componente BackgroundWorker.

Antes de nos aprofundarmos em suas propriedades e métodos iremos montar a estrutura principal de nosso

exemplo prático. Para isto, iremos adicionar um “Backgroundworker” situado na palheta de componentes chamada

“Components”, uma barra de progresso “Progressbar” e mais dois botões denominados “Iniciar” para iniciar o progresso

e “Cancelar” para cancelar o progresso da tarefa. A estrutura do formulário deverá ficar idêntica ao da Imagem 02.

Page 4: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Figura 02: Exemplo Prático.

O componente “Backgroundworker” não é visual, portanto, o mesmo ficará situado na parte inferior de nossa

tela. Ver Imagem 03 para maiores detalhes.

Figura 03. BackgroundWorker.

Ao clicar sobre o componente podemos conferir algumas propriedades importantes, como:

WorkerReportsProgress: Propriedade booleana para indicar se o componente suporta a utilização de uma barra

de progresso.

WorkerSupportsCancellation: Propriedade Booleana para indicar o cancelamento da operação iniciada.

Ver Imagem 04.

Figura 04: Propriedades.

Faremos o uso de três principais eventos, sendo:

Page 5: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

DoWork:

Esse evento é gerado quando iniciamos a operação que executa a rotina especificada. Temos o controle através deste

evento periodicamente sobre o valor da propriedade “CancellationPending” para cancelar a operação ou caso contrário para

continuar o processo normalmente.

ProgressChanged: Evento disparado para preencher a barra de progresso através da propriedade “e.ProgressPercentage”.

RunWorkerCompleted: Ocorre quando a operação foi concluída, cancelada ou gerou uma exceção.

Para visualizar estes eventos, verificar Imagem 05.

Figura 05: Eventos.

Codificando o exemplo

Antes de partirmos para codificação deveremos configurar para “true” as propriedades “WorkerReportsProgress” e

“WorkerSupportsCancellation”, para permitir a implementação da barra de progresso e suportar cancelamento de tarefas

respectivamente.

Adicione o seguinte namespace para trabalharmos com “Threads”

using System.Threading;

No método “backgroundWorker1_DoWork” iremos programar um laço simples, nos dando a impressão de

processamento de alguma rotina. Ele alimentará uma lista de inteiros e a barra de progresso através do método

“ReportProgress” simulará uma pausa de “0,5” segundos através da propriedade “Thread.Sleep”. Faremos também uma

verificação se o processo foi cancelado para em seguida abortar a operação. Ver Listagem 01.

Page 6: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

List<int> temp = new List<int>();

for (int i = 0; i <= 10; i++)

{

if (backgroundWorker1.CancellationPending)

{

e.Cancel = true;

break;

}

backgroundWorker1.ReportProgress(i * 10);

Thread.Sleep(500);

temp.Add(i);

}

e.Result = temp;

}

Listagem 01.

No evento “backgroundWorker1_ProgressChanged”, alimentaremos a “progressbar” através da propriedade

“e.ProgressPercentage”.

private void backgroundWorker1_ProgressChanged(object sender,

ProgressChangedEventArgs e)

{

this.progressBar1.Value = e.ProgressPercentage;

}

Para o método “backgroundWorker1_RunWorkerCompleted” e pelo argumento

“RunWorkerCompletedEventArgs” conseguimos analisar se o processo foi concluído ou

cancelado.

private void backgroundWorker1_RunWorkerCompleted(object sender,

RunWorkerCompletedEventArgs e)

{

if (e.Cancelled)

{

MessageBox.Show("Rotina Cancelada!!");

}

else

{

MessageBox.Show("Rotina Completada!!");

}

}

Para o evento “Click” do botão “Iniciar” faremos uma verificação se o

“backgroundWorker” está executando alguma ação assíncrona, caso constrário

iniciaremos a operação com o método “backgroundWorker1.RunWorkerAsync()”.

private void btnIniciar_Click(object sender, EventArgs e)

{

if (backgroundWorker1.IsBusy != true)

{

backgroundWorker1.RunWorkerAsync();

}

}

E para cancelar a operação invocaremos o método

“backgroundWorker1.CancelAsync()”.

Page 7: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

private void btnCancelar_Click(object sender, EventArgs e)

{

backgroundWorker1.CancelAsync();

}

Na Imagem 06 podemos conferir o resultado do processo iniciado.

Figura 06: Rotina Completada.

Já na Figura 07 será cancelado o processo ao clicar no botão “Cancelar”. Note que a barra de progresso

também ficou paralisada no momento que desejamos, ou seja, toda a rotina foi abortada.

Figura 07: Rotina Cancelada.

Page 8: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Conclusões

Podemos aprender neste artigo todos os macetes necessários para trabalhar com o componente

“BackgroundWorker”.

Fique à vontade para implementar em seus sistemas da maneira que desejar.

Fica aí a dica deste mês.

Um abraço.

Referências

https://msdn.microsoft.com/pt-br/library/system.componentmodel.backgroundworker(v=vs.110).aspx

Sobre o Autor Thiago Cavalheiro Montebugnoli Adora aprender novas tecnologias. Formado

pela Faculdade de Tecnologia de Botucatu - SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Como experiências

profissionais mais recentes, possui em seu currículo sua atualização no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP e atualmente coordena a equipe da Coordenadoria Tecnologia da Informação no IFSP - Instituto Federal do Estado de São Paulo em Avaré. Além

disso, é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified

Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

E-mail: [email protected]

Page 9: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Single Page Application com AngularJS

Introdução Com o avanço das aplicações web voltadas para smartphones as conhecidas como Single Page Applications se

tornaram cada dia mais comum. Essas aplicações são nada mais que uma página HTML que carrega o conteúdo sem

que a página seja recarregada dando assim a impressão de que o usuário está usando uma aplicação nativa e não

navegando em um site. Antes de o Angular ser criado era muito comum que esse conteúdo fosse recarregado via requisições AJAX e

que toda chamada necessitava ser tratada manualmente gerando um trabalho muito grande que dificultava a

manutenção e os testes. No artigo de hoje nós iremos criar uma aplicação para uma banda com uma página inicial, uma página de

sobre e uma página de contato.

HTML Em nosso aplicativo nós iremos utilizar o Bootstrap, uma biblioteca desenvolvida pelo Twitter amplamente

utilizada no mundo inteiro que nos fornece várias facilidades.

Para começarmos nos iremos criar o nosso index.html que servirá como um esqueleto para toda a nossa aplicação.

Arquivo index.html

<!doctype html>

<html>

<head>

<meta charset="UTF-8">

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js">

</script>

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-

route.js"></script>

<script src="script.js"></script>

<link rel="stylesheet"

href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />

</head>

<body>

<header>

<nav class="navbar navbar-default">

<div class="container">

<div class="navbar-header">

<a class="navbar-brand" href="/">The Club Band</a>

</div>

<ul class="nav navbar-nav navbar-right">

<li><a href="#">Início</a></li>

<li><a href="#sobre">Sobre</a></li>

<li><a href="#contato">Contato</a></li>

</ul>

</div>

Page 10: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

</nav>

</header>

<div id="main">

<!-- aqui é o local onde as views serão -->

<!-- injetadas pelo Angular -->

</div>

</body>

</html>

Como é possível observar o arquivo é bastante simples. Logo no início nós utilizamos a biblioteca do

AngularJS e a diretiva responsável pelas rotas no Angular e depois o arquivo CSS com os estilos do Bootstrap.

No HTML existem dois pontos importantes, o primeiro é a nossa navbar que utiliza o estilo padrão do

Bootstrap, mais informações de como utilizar a navbar podem ser encontrados na documentação oficial no endereço

http://getbootstrap.com/components/#navbar. O segundo ponto importante é a div com o id main, é nela que o

Angular irá injetar o conteúdo de cada view.

É importante notar que os endereços dos links estão iniciando com #, isso é utilizado pois evita que o

navegador trate o link como um link comum e tente recarregar a nossa página.

Criação do Módulo e do Controller O passo seguinte será criarmos o nosso módulo e o controller responsáveis por iniciar nossa aplicação. Eles

serão criados no arquivo script.js que é chamado pelo nosso index.html. Vamos ao arquivo:

// Arquivo script.js

var theClubApp = angular.module('theClubApp', []);

theClubApp.controller('controllerPrincipal', function($scope) {

$scope.mensagemInicial = 'Bem-vindos a página da The Club Band!';

});

Se você tiver dúvida como o escopo do Angular funciona aconselho que você leia o artigo postado na edição

anterior da The Club intitulado de Introdução aos Escopos do AngularJS.

Se você testar a aplicação verá que nada acontece, isso é porque nós não iniciamos a theClubApp no

index.html, portanto vamos adaptá-lo um pouco. As mudanças estão em negrito.

Arquivo index.html

<!doctype html>

<html ng-app=”theClubApp”>

<head>

<meta charset="UTF-8">

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js">

</script>

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-

route.js"></script>

Page 11: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

<link rel="stylesheet"

href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />

</head>

<body ng-controller=”controllerPrincipal”>

<header>

<nav class="navbar navbar-default">

<div class="container">

<div class="navbar-header">

<a class="navbar-brand" href="#">The Club Band</a>

</div>

<ul class="nav navbar-nav navbar-right">

<li><a href="#">Início</a></li>

<li><a href="#sobre">Sobre</a></li>

<li><a href="#contato">Contato</a></li>

</ul>

</div>

</nav>

</header>

<div id="main">

{{ mensagemInicial }}

<!-- aqui é o local onde as views serão -->

<!-- injetadas pelo Angular -->

</div>

</body>

</html>

Dentro de nossa div main nós incluímos a mensagem inicial e agora que a nossa aplicação e nosso módulos

foram instanciados vamos começar a trabalhar em como injetar o conteúdo das novas páginas da nossa aplicação.

Injetando as páginas em nosso esqueleto O ng-view uma diretiva responsável por injetar o HTML da rota selecionada em nosso esqueleto e exibir ao

navegador. Nós iremos adicionar a tag ng-view em nossa div main para dizer ao Angular onde injetar nossas páginas.

Arquivo index.html

...

</header>

<div id="main">

<!-- aqui é o local onde as views serão -->

<!-- injetadas pelo Angular -->

<div ng-view></div>

</div>

</body>

Page 12: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Configurando as rotas e as views

Como nossa página será uma Single Page Application nós não queremos que a página seja recarregada em

momento algum, para isso nós iremos utilizar a $routeProvider para que o Angular possa tomar conta de toda a

mágica. Vamos voltar ao nosso arquivo Java Script.

// Arquivo script.js

var theClubApp = angular.module('theClubApp', ['ngRoute']);

theClubApp.config(function($routeProvider){

$routeProvider

// rota para a página início

.when('/', {

templateUrl : 'templates/inicio.html',

controller : 'controllerPrincipal'

})

// rota para a página sobre

.when('/sobre, {

templateUrl : 'templates/sobre.html',

controller : 'controllerSobre'

})

// rota para a página contato

.when('/contato, {

templateUrl : 'templates/contato.html',

controller : 'controllerContato'

});

});

theClubApp.controller('controllerPrincipal', function($scope) {

$scope.mensagemInicial = 'Bem-vindos a página da The Club Band!';

});

theClubApp.controller('controllerSobre', function($scope) {

$scope.mensagemInicial = 'A The Club Band é uma banda fictícia criada para

o artigo de como criar uma Single Page Application utilizando o framework

AngularJS.';

});

theClubApp.controller('controllerContato', function($scope) {

$scope.mensagemInicial = 'Se você quiser nos contratar basta entrar em

contato com nosso empresário.';

});

Agora nós definimos nossas rotas através do $routeProvider, o Angular irá buscar o arquivo

inicio.html quando a sua rota for selecionada, o mesmo acontecerá com as outras rotas. Para finalizar este artigo

vamos criar os templates:

<!-- inicio.html -->

<div class="text-center">

<h1>Início</h1>

<p>{{ mensagemInicial }}</p>

</div>

Page 13: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

<!-- sobre.html -->

<div class="text-center">

<h1>Sobre a The Club Band</h1>

<p>{{ mensagemInicial }}</p>

</div>

<!-- contato.html -->

<div class="text-center">

<h1>Contato</h1>

<p>{{ mensagemInicial }}</p>

</div>

Importante: As rotas no Angular somente funcionarão se você estiver rodando em um servidor, ou seja, se você estiver

testando a aplicação em seu computador local certifique-se que a aplicação rode na url http://localhost ou em outro

ambiente.

Conclusão

No artigo de hoje nós aprendemos como criar um Single Page Application de forma rápida e simples. Com o

conhecimento adquirido hoje será possível criar aplicações mais robustas e dinâmicas utilizando o framework

AngularJS.

Sobre o Autor

Ricardo Barbosa Crivelli, mais conhecido como Rico Crivelli, é formado como Bacharel

em Sistemas de Informação e Licenciado em Computação pela Universidade Estadual do Norte do Paraná,

atualmente é Técnico em TI no Instituto Federal de São Paulo – Câmpus Avaré. Tem como especialidade a linguagem PHP e o framework Symfony, apesar de adorar trabalhar com front-end e desenvolvimento

mobile e possuir as certificações COBiT 4.1 Foundation e Delphi 2006 Developer.

E-mail: [email protected]

Page 14: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Linguagem C# - Ftp de Arquivos – Parte 2

Caro amigo, neste mês irei explorar a segunda parte do artigo sobre FTP de arquivos utilizando a linguagem

C# junto com a plataforma Windows Forms. No mês passado criamos uma classe chamada “Ftp”, contendo o método

necessário para a realização do Upload de arquivos. Neste mês de Fevereiro irei ensiná-los a realizar o “Download”

de arquivos deste mesmo servidor. Para isto criarei uma interface implementando métodos desta mesma classe Ftp.

Utilizaremos as duas classes descritas no artigo de Janeiro, sendo a: “FtpWebRequest” e a

“FtpWebResponse”. Para maiores detalhes recomendo a leitura da primeira parte deste artigo.

Reutilizando a Classe Ftp

Iremos implementar mais dois métodos na classe FTP, sendo:

“ListarArquivos”: Responsável por trazer todos os arquivos contidos no servidor FTP, nos permitindo fazer a escolha

do arquivo a ser baixado.

“Download”: Rotina necessária para realizar o download do arquivo escolhido.

Deveremos também implementar mais alguns atributos, como: “ftpResponse”, “ftpStream” e “bufferSize”.

Ambos os métodos e atributos serão explicados a seguir.

Declarando os atributos necessários:

private FtpWebResponse ftpResponse = null;

private Stream ftpStream = null;

private int bufferSize = 2048;

Na função “Download” passaremos por parâmetros o caminho do arquivo contido no servidor FTP e na

máquina local. Teremos um retorno booleano para indicar se a rotina foi realizada ou não com sucesso.

Primeiramente instanciamos a classe “FtpWebRequest” fornecendo o endereço do servidor e local. Para o método

“Credentials” atribuímos o usuário e senha do FTP. Utilizaremos configurações como “UseBinary” para arquivos

binários, “UsePassive” para definir o comportamento do processo de transferência de dados de um aplicativo,

“KeepAlive” para especificar se a conexão de controle para o servidor FTP é fechada depois que a solicitação for

concluída. O próximo passo seria identificar o tipo de tarefa através do atributo “Method”.

Para isto escolheremos “DownloadFile” e logo em seguida estabelecemos um retorno do servidor FTP através

do método “GetResponse”. O atributo “ftpStream” irá nos auxiliar para testarmos o “Download” do arquivo através

de uma rotina “Try/Catch”.

Ver Listagem 01.

Page 15: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

public bool Download(string remoteFile, string localFile)

{

try

{

ftpRequest = (FtpWebRequest)FtpWebRequest.Create(enderecoFtp + "/" +

remoteFile);

ftpRequest.Credentials = new NetworkCredential(usuario, senha);

ftpRequest.UseBinary = true;

ftpRequest.UsePassive = true;

ftpRequest.KeepAlive = true;

ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;

ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();

ftpStream = ftpResponse.GetResponseStream();

FileStream localFileStream = new FileStream(localFile, FileMode.Create);

byte[] byteBuffer = new byte[bufferSize];

int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);

try

{

while (bytesRead > 0)

{

localFileStream.Write(byteBuffer, 0, bytesRead);

bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);

}

}

catch

{

return false;

}

localFileStream.Close();

ftpStream.Close();

ftpResponse.Close();

ftpRequest = null;

}

catch

{

return false;

}

return true;

}

Listagem 1.

A rotina “Listararquivos” possui como parâmetro de entrada o diretório onde os arquivos se encontram no

servidor FTP. Ela nos retorna um Array de Strings, contendo todos os nomes dos arquivos do endereço fornecido.

Iniciamente utilizaremos exatamente as mesmas opções descritas no método “Download”. Usaremos o método

“WebRequestMethods.Ftp.ListDirectory” para listar os arquivos do diretório indicado. Iremos ler linha por linha

armazenando na variável “directoryRaw” e separada por um pipe “|”. Por final, retornaremos a variável “directoryList”

contendo todos os nomes dos arquivos.

Ver Listagem 02.

Page 16: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

public string[] ListarArquivos(string directory)

{

try

{

ftpRequest = (FtpWebRequest)FtpWebRequest.Create(enderecoFtp + "/" +

directory);

ftpRequest.Credentials = new NetworkCredential(usuario, senha);

ftpRequest.UseBinary = true;

ftpRequest.UsePassive = true;

ftpRequest.KeepAlive = true;

ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;

ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();

ftpStream = ftpResponse.GetResponseStream();

StreamReader ftpReader = new StreamReader(ftpStream);

string directoryRaw = null;

try

{

while (ftpReader.Peek() != -1) {

directoryRaw += ftpReader.ReadLine() + "|"; }

}

catch { }

ftpReader.Close();

ftpStream.Close();

ftpResponse.Close();

ftpRequest = null;

try

{

string[] directoryList = directoryRaw.Split("|".ToCharArray());

return directoryList;

}

catch { }

}

catch { }

return new string[] { "" };

}

Listagem 02.

Criando um exemplo prático

Nosso formulário deverá conter a seguinte estrutura: 4 pares de Labels e TextBox sendo (Endereço Ftp,

Usuário, Senha e Download em), um Listbox contendo o descritivo “Arquivos”, onde serão adicionados os arquivos

contidos no servidor FTP e o botão “Download”, o qual fará o trabalho de baixar o arquivo no servidor FTP. Ver

Imagem 01.

Page 17: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Figura 01: Criando a interface gráfica para consumir a classe Ftp.

O método “RecuperarArquivosFTP”, que fará o trabalho de listar todos os arquivos do servidor FTP através

do método “ListarArquivos” contidos na classe FTP. Invocaremos o mesmo logo após o método

“InitializeComponent”, ou seja, quando carregamos os componentes na tela.

public FrmFTPDownload()

{

InitializeComponent();

RecuperarArquivosFTP();

}

private void RecuperarArquivosFTP()

{

Ftp ftp = new Ftp(txtEndereco.Text, txtUsuario.Text, txtSenha.Text);

string[] detailDirectoryListing = ftp.ListarArquivos("/thiago");

for (int i = 0; i < detailDirectoryListing.Count(); i++)

{

lstArquivos.Items.Add(detailDirectoryListing[i]);

}

}

No evento “Click” do botão “Download” usaremos a função “consistencias” (Implementada no artigo do mês

de Janeiro). Esta função terá algumas pequenas alterações, como por exemplo a inclusão do campo “Download em:”,

ver código abaixo:

Page 18: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

if (txtDownload.Text.Length <= 0)

{

MessageBox.Show("O campo Download é de preenchimento obrigatório!",

"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);

return false;

}

Por este motivo não incluirei por inteiro a mesma em nosso artigo deste mês.

Receberemos o nome do arquivo através da seleção do mesmo no ListBox. Através da instância da classe

FTP passaremos para o método construtor os dados do endereço, usuário e senha e em seguida atribuímos para o

método “Ftp.Download” o caminho absoluto do arquivo localizado no servidor FTP e o caminho absoluto local.

Passaremos uma mensagem informando se o processo foi realizado com sucesso através do “MessageBox”.

private void btnDownload_Click(object sender, EventArgs e)

{

if (consistencias() == true)

{

String nomeArquivo = lstArquivos.SelectedItem.ToString();

Ftp ftp = new Ftp(txtEndereco.Text, txtUsuario.Text, txtSenha.Text);

if (ftp.Download("thiago/" + nomeArquivo, txtDownload.Text + nomeArquivo))

MessageBox.Show(string.Format("Download do arquivo {0} realizado com

sucesso!", nomeArquivo), "Informação", MessageBoxButtons.OK,

MessageBoxIcon.Information);

}

else{

MessageBox.Show(string.Format("Ocorreu uma falha no download do arquivo {0}!",

nomeArquivo), "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}

Page 19: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Podemos conferir o exemplo em Run-time na Figura 02.

Figura 02: Exemplo em Run-Time.

Conclusões

Nesta segunda e última parte aprendemos a implementar o uso de download de arquivos via FTP. Assim

completamos o ciclo completo das principais tarefas envolvendo FTP através da linguagem C#. Fica aí a dica, um

abraço e até o mês que vem!

Referências

https://msdn.microsoft.com/pt-br/library/system.net.ftpwebresponse(v=vs.110).aspx

https://msdn.microsoft.com/pt-br/library/system.net.ftpwebrequest(v=vs.110).aspx

Sobre o Autor

Thiago Cavalheiro Montebugnoli, adora aprender novas tecnologias. Formado pela Faculdade de

Tecnologia de Botucatu – SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Como experiências profissionais mais recentes, possui em seu currículo sua atuação no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP e atualmente compõe a equipe da Coordenadoria Tecnologia da Informação no IFSP – Instituto Federal do Estado de São Paulo em Avaré. Além disso, é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD- Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

E-mail: [email protected]

Page 20: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

THVDataSet – DataSet baseado em Memória

Interessante como existem várias alternativas para manipulação de dados em memória por parte do Delphi; o

que vamos dar foco neste artigo é a manipulação em grande escala de informações para os controles Data-Aware

utilizando desta vez um novo componente, mais flexível, batizado de THVDataSet. Neste artigo vamos ver sua utilização

e perceber como ele muito mais rápido que qualquer outro componente disponível opensource a ser disponibilizado

em uma Grid – e perceber também que está sendo lido e carregado tudo em memória – e porque não aproveitar as

vantagens de um objeto do tipo TMemoryStream para estas funcionalidades? Na edição anterior abordamos um componente descendente diretamente de TStream, onde podemos carregar

e salvar nossos registros (persistência) de uma forma muito transparente para o usuário por ser também descendente

de um TDataSet. O aplicativo tem ao seu lado um “banco de dados” muito prático e funcional – ilimitado o número de registros

– e também desenvolvemos uma funcionalidade original para o processamento de layout (header) para que nosso

banco pudesse ser aberto antes de ser lido. Agora no entanto queremos uma funcionalidade semelhante – mas sem

persistência – porque queremos que tudo seja carregado em memória e seja lido, editado, excluído, enfim, como um

descendente tradicional de um TDataSet – só que tudo em memória. Talvez a pergunta mais fácil e óbvia seria – “porque então não utilizamos um objeto de TClientDataSet que já

vem no Delphi?” – “ele também é baseado em memória!” – Sim, é verdade, é baseado em memória e já vem no Delphi,

desde a versão 3, porém o questionador destas perguntas não sei se já percebeu que este mesmo objeto de

TClientDataSet a qual se refere não é rápido assim. Se for para poucos registros, tudo bem! Mas não queremos para

poucos registros. Queremos testar na base dos 1.000.000 de registros em memória e com excelente resposta de rapidez!

E aí, o que dizer agora? A resposta intrigante para estas perguntas desafiadoras trago aqui como boa notícia! E digo mais, porque em

poucos segundos isso será real – será carregado um milhão de itens em um DBGrid associado a este nosso novo

componente – contrariando a lentidão do tradicional TClientDataSet que levará MINUTOS para executar a mesma

operação no mesmo TDBGrid. Vamos aos fatos? Boa leitura!

Comparativo de velocidade Vamos primeiramente abordar em uma tabela abaixo o quanto de tempo necessário para carregar

hipoteticamente uma coluna do tipo integer – o nome do atributo é “Cd_User”, e vamos inserir dinamicamente (através

de uma variável auxiliadora que fará o papel de incremento um a um) o conjunto de um milhão de itens inteiros. O

objetivo deste procedimento é testar velocidade – porque como dito anteriormente o foco deste nosso componente é

“disparar” velocidade trazendo agilidade em nossos processamentos em uma DBGrid – daí a criação do nosso

“componente-foguete”. Resultado dos testes:

Componente TClientDataSet THVDataSet

Carregar e ler um milhão de

registros

Tempo: 5 minutos e 17 segundos 5 segundos

Page 21: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Figura 01 – Mensagem de retorno da confirmação do teste – componente TClientDataSet.

Figura 02 – Mensagem de retorno da confirmação do teste – componente THVDataSet.

Figura 03 – Ilustração dos componentes carregados – THVDataSet e TClientDataSet.

Se perceber bem, todos ambos os componentes carregaram com sucesso. O problema não é esse – eles funcionam

e bem – o problema é O TEMPO que é levado para tal – pois enquanto um levará de cinco a seis minutos, o nosso

componente levará de cinco a seis segundos! E isso é ótimo quando o que se quer é carregar milhares e milhões de

registros de uma vez. Tudo funciona muito bem, claro, mas há limitações quanto a memória disponível – não vamos

carregar bilhões de itens porque obviamente estourará a memória – precisamos ser sensatos porque nem tudo são flores

– se está inserindo itens dinamicamente em um objeto de TDBGrid, leve-se em conta que esses dados consomem

memória além do THVDataSet – e do TDBGrid também.

Claro que não é a forma mais rápida de todas – existem alternativas melhores – por exemplo – estamos lendo

para um TDBGrid – se quiséssemos rapidez de verdade – tiraríamos o TDBGrid e leríamos a partir de um classe

descendente de um TList – aí sim carregaríamos este conjunto de um milhão de registros em milésimos de segundo! E

isso é ótimo. Mas o que queremos neste foco é abordar a velocidade deste processamento aliado também ao

componente TDBGrid (coisa que um TList não tem suporte) e por isso a velocidade “cai” um pouco (mas nem tanto,

como já vimos acima). O resultado é que tudo funciona as mil maravilhas. Claro que o quesito memória conta e muito –

Page 22: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

para os nossos testes foi testado processador 2.50 GHz com 4GB de RAM. Recomendável sempre a partir destas

configurações para mais – a fim de se obter resultados ainda mais rápidos.

Vamos inserir abaixo um pequeno trecho do fonte responsável para a implementação desta nossa função de teste

– foi utilizado uma classe chamada “TStopWatch” para auxiliar na precisão da medição dos nossos resultados (algo como

um cronômetro bem preciso) – utilizando das funções da API Kernel32 do Windows – QueryPerformanceFrequency e

QueryPerformanceCounter para fazer a medição do tempo com uma resposta em milésimos de segundos, muito eficiente

e robusto suas respostas de testes.

const

cUserFieldName = 'Cd_User';

const

cDefaultStopWatchInitialText = '0 elapsed milliseconds.';

cStopWatchSuccess = 'Tested Component: %s.'#13#10'%s elapsed

milliseconds.';

implementation

uses StopWatch;

procedure TForm1.Button2Click(Sender: TObject);

var

i, counter: integer;

sw : TStopWatch;

begin

HVDataSet1.Active := True;

HVDataSet1.DeleteAll;

counter := StrToIntDef(Edit1.Text, 10);

stStopWatch.Caption := cDefaultStopWatchInitialText;

HVDataSet1.DisableControls;

sw := TStopWatch.Create;

try

pnlLoading.Visible := True;

Screen.Cursor := crSQLWait;

try

sw.Start;

for i := 0 to counter do

begin

with HVDataSet1 do

begin

Append;

FieldByName(cUserFieldName).AsInteger := i;

Post;

end;

Application.ProcessMessages;

end;

Finally

Page 23: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

pnlLoading.Visible := False;

Screen.Cursor := crDefault;

HVDataSet1.EnableControls;

sw.Stop;

stStopWatch.Caption := 'Elapsed ' +

FormatMillisecondsToDateTime(sw.ElapsedMilliseconds);

end;

finally

FreeAndNil(sw);

end;

HVDataSet1.First;

Application.MessageBox(PChar(Format(cStopWatchSuccess, ['THVDataSet',

stStopWatch.Caption])), 'Information', MB_OK + MB_ICONINFORMATION);

end;

Utilizando o componente na prática

Agora vamos demonstrar o componente na prática, através de um aplicativo de teste para inserir vários registros

e medindo o tempo gasto – o propósito deste programa é carregar um milhão de registros e ver quanto tempo ele vai

levar pra fazer isso – serão três colunas criadas dinamicamente pelo THVDataSet (uma do tipo inteiro, outra do tipo

string e outra do tipo time) e com uma função semelhante como visto anteriormente vamos implementar esta

funcionalidade aqui. Alguns fatores novos interessantes foram incluídos para facilitar e agilizar a performance dos nossos

testes; vamos portanto elencar eles agora:

1. Inclusão do framework FastMM4 (Fast Memory Manager 4.991);

2. Inclusão do framework Synopse (função Int64ToUTF8);

3. Inclusão da thread TProgressThread (criada por mim);

4. Inclusão da classe opensource TStopWatch.

Todas essas classes mencionadas acima são de suma importância para agilizar os testes através de um melhor

gerenciamento de memória, principalmente pelo framework FastMM4. Nossos testes foram realizados em Delphi 7.

Page 24: rbosa Crivelli continua escrevendo sobre AngularJS, com o ... · Ricardo Barbosa Crivelli continua escrevendo sobre AngularJS, com o artigo entitulado “AngularJS - Single Page App“.

Figuras 04, 05 – Demonstração do aplicativo de teste do componente THVDataSet.

Para este teste foi levado o tempo médio de 36 segundos para um milhão de registros criados em três colunas

dinamicamente – isso tudo em memória.

Conclusão

Vimos uma implementação em memória muito prática e veloz, através de um componente chamado de

THVDataSet. Com ele pudemos ver a sua eficiência superior ao componente tradicional do Delphi (TClientDataSet) onde

o foco é a velocidade em milhares e milhões de registros em pouquíssimo tempo. É claro que não se tem a intenção de

substituir o TClientDataSet no seu emprego normal; nosso THVDataSet é um descendente de TMemoryStream e não tem

as características de um TClientDataSet embutidas nele (índices, agrupamentos, etc) – mas para armazenamento

temporário de grandes quantidades de dados e suas manipulações via componentes Data-Aware poderão com certeza

contar com ele! Um grande abraço e até a próxima!

Utilizem com prazer este grande componente “armazenador de velocidade”!!!

Sobre o Autor

Hamden Vogel Consultor TheClub

E-mail: [email protected]