segunda-feira, 25 de outubro de 2010

Download de arquivos da Internet

Olá pessoal, grande satisfação poder estar de volta ao blog depois de um bom tempo sem postar. Não que eu tenha parado de desenvolver, estou no Delphi quase que direto desenvolvendo sistemas e sites e compartilhando o tempo com manutenção de computadores aqui na loja, orçamentos, vendas de equipamentos de informática, entre outros. Devido a alguns comentários que recebi em outros posts aqui do blog e até e-mails que recebi de delphianos, volto a elaborar e postar este artigo.
Bom, então para começarmos este artigo onde irei mostrar como gerenciar o download de arquivos da internet, saber qual seu tamanho e taxa de transferência, usaremos o Delphi 2007 for Win32, onde inicialmente criaremos um novo projeto e adicionaremos os seguintes componentes:
1 - Label ('lblURL'). Caption: "URL para Download"
2 - Edit ('edtURL')
3 - Button ('btDownload'). Caption: "Download"
4 - Gauge ('Gauge1')
5 - Label ('LblDownload'). Caption: "Aguardando..."
6 - Label ('lblVelocidade'). Caption: "0 kbp/s"
7 - IdHTTP ('IdHTTP1')
8 - SaveDialog ('SaveDialog1')

Adicionados os componentes ao formulário, organize-os conforme imagem abaixo onde daremos continuidade iniciando a codificação das ações do sistema.
Início do Download
Iniciaremos a codificação do aplicativo a partir do evento WorkBegin do componente IdHTTP1, o qual é disparado no momento em que o Download do arquivo é iniciado, onde iremos declarar dentro do bloco Public da unit uma variável para armazenar o horário de início do Download, adicionando a seguinte linha:
FStartDate: TDateTime;

Em seguida, fazendo a codificação do evento adicionando o seguinte código ao mesmo:
procedure TForm1.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
begin
{limpa a barra de progresso}
Gauge1.Progress := 0;
{define o tamanho máximo para o Gauge}
Gauge1.MaxValue := AWorkCountMax;
{Marcando o inicio do Download}
FStartDate:= Now;
end;

Avanço do Download
O controle do avanço do Download faremos a partir do evento OnWork do componente IdHTTP1, o qual será o responsável por incrementar o percentual de conclusão do download a cada pacote de bytes trazidos no objeto de download. Baseados no tamanho total do arquivo, a cada pacote realizamos uma conversão dos valores incrementando o percentual até a conclusão do trabalho. Adicione o código a seguir ao componente:
procedure TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;AWorkCount: Integer);
begin
{a cada conjunto de bytes trazidos pelo componente, incrementamos o Gauge}
Gauge1.Progress := AWorkCount;
{mostra no label o total de bytes e o progresso do download em bytes}
LblDownload.Caption := 'Baixando '+FormatFloat('#0.00',(AWorkCount/1024)/1024)+'MB de '+FormatFloat('#0.00',(Gauge1.MaxValue/1024)/1024)+'MB';
{reescreve os valores no formulário}
if AWorkMode = wmRead then
begin
//Marca o tempo percorrido
ElapsedTime := SecondsBetween(Now,FStartDate);
if ElapsedTime > 0 then
begin
//Calcula a velocidade com base nos arquivos transferidos e tempo percorrido
lblVelocidade.Caption := Format('%s Kb/s', [FormatFloat('0.00',(AWorkCount/1024)/ElapsedTime)]);
Application.ProcessMessages;
end;
end;
Repaint;
end;

Encerramento do Download
Ao receber todos os bytes do arquivo solicitado através da URL, utilizaremos este evento para informar ao usuário que a tarefa está concluída, exibindo uma simples mensagem no Caption do LblDownload, adicionado o código a seguir:
procedure TForm1.IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
{conclusão do trabalho, fim do download}
LblDownload.Caption := 'Download concluído!';
end;

Controle do Download
Antes de codificarmos o botão para iniciar o processo de trabalho do componente, iremos adicionar uma nova function que irá manter as atividades e mensagens do formulário atualizadas durante o processo de download que ocorre através de um Stream de arquivos criado, e que irá armazenando o arquivo na medida em que será recebido da web. Há também um controle de exceções caso algum erro ocorra durante o download e ao finalizar, a remoção da variável de stream da memória. Declare dentro do bloco Public da unit a seguinte function:
procedure DownloadFile(SourceFile, FromFile: String);

Utilizando as teclas de atalho Shift+Ctrl+C sobre a função declarada para que o Delphi faça a implementação da mesma, adicione o código abaixo analisando-o de acordo com as ações de cada bloco acompanhados por comentários explicativos.
procedure TForm1.DownloadFile(SourceFile, FromFile: String);
var
fsFromFile: TFileStream;
begin
{atualiza e processa as ações ocorrendo na aplicação}
Application.ProcessMessages;
{cria um stream temporário para o download}
fsFromFile := TFileStream.Create( FromFile, fmCreate );
try
try
{obtem o arquivo solicitado na URL e salva-o em disco}
idHTTP1.Get( SourceFile, fsFromFile );
except
on Error: Exception do
begin
{tratamento dos erros quando houver}
ShowMessage('O seguinte erro ocorreu durante o download:'+#13+Error.Message );
Raise;
end;
end;
finally
{limpa a variável da memória e desconecta o componente}
fsFromFile.Free;
idHTTP1.Disconnect
end;
end;

DICA: caso algum código não seja reconhecido pela não declaração das uses como por exemplo que poderá ocorrer com o Type TFileStream, posicione o cursor sobre o mesmo e usando as teclas Shift+Ctrl+A, selecione aquela que se refere ao tipo declarado e pressione Enter que o mesmo será adicionado automaticamente nas declarações do formulário.

Download
Agora sim, para que o Download de fato aconteça, precisamos codificar o botão responsável pelo Start dos demais eventos e funções que já vimos. Com um duplo clique sobre o botão, adicione o código a seguir, o qual fará uma verificação para saber se realmente há algum valor informado no Edit da URL e em seguida passando para o processo de tratamento do nome a ser atribuído ao arquivo a ser salvo e a escolha de um local no disco para o armazenamento, iniciando dessa forma a transferência do arquivo.
procedure TForm1.btDownloadClick(Sender: TObject);
var
vArquivo: TFileStream;
vFileName : String;
I: Integer;
begin
{somente inicia se houver uma URL no campo}
if Length(edtURL.Text) > 0 then
begin
{Passando a URL para a variável a fim de obter o nome do arquivo}
vFileName := edtURL.Text;
{inicia laço e pesquisa pela última bara para obter filename}
for I := 0 to Length(vFileName) - 1 do
begin
{se encontrar uma barra deleta os caracteres que antecedem a mesma.
Se chegar na última bara permanece apenas o nome do arquivo}
if Pos('/',vFileName) > 0 then
Delete(vFileName,1,Pos('/',vFileName));
end;
{abre o diálogo já preenchido com o nome e solicita local de
armazenamento do download}
SaveDialog1.FileName := vFileName;
if SaveDialog1.Execute then
begin
{inicia o download do arquivo}
DownloadFile(edtURL.Text,SaveDialog1.FileName);
end;
end else
MessageDlg('Informe a URL do Download!',mtWarning,[mbOK],0);
end;

Utilize as teclas Ctrl+F9 para compilar o aplicativo e verificar se não há nenhum problema de codificação e em seguida as teclas Ctrl+Shif+F9 para executar o aplicativo e poder comprovar o seu funcionamento. Adicione uma URL válida ao componente de textos e clique sobre o botão para iniciar o Download, escolha um local para armazenar o arquivo e observe o funcionamento/transferência do arquivo, conforme imagem abaixo:
Para aqueles que quiserem efetuar o download dos fontes, CLIQUE AQUI para ser redirecionado ao site onde estão hospedados os artigos (se preferir, desenvolva o aplicativo antes e faça o download posteriormente usando o aplicativo para poder testá-lo). Abraço pessoal e até o próximo.

Um comentário:

Mateus André Chies disse...

Buenas
Muito Bom esse POST, vai ser muito util para futuros downloads de aplicativos.