DICAS

Visite a biblioteca de dicas da comunidade.

Saiba mais

ARTIGOS

Abordagens detalhadas sobre assuntos diversos.

Saiba mais

INICIANTES

Aprenda a programar de um modo simples e fácil.

Saiba mais

DOWNLOADS

Acesse os materiais exclusivos aos membros.

Saiba mais
voltar

PARA QUEM GOSTA DE DELPHI

Como fazer Download de Arquivos com Progresso do andamento?

Fala galera do Show Delphi, tudo beleza?

Hoje estava precisando implementar nos meus sistemas um mecanismo para baixar arquivos.

Então pesquisando vi que podia fazer isso utilizando o TIDHttp, que é um componente do Indy que já acompanha o Delphi por padrão e também é possível instalar no Lazarus gratuitamente.

Legal, basicamente é assim: IDHttp1.Get(‘seu link’, variavelStream).

Bacana, vi que funcionava assim, mas eu queria que fosse exibido o andamento do download, para os casos de arquivos maiores.

Tentei algumas formas utilizando diretamente o TIDHttp, mas não tinha conseguido obter sucesso.
Então continuei pesquisando e encontrei um post no stackoverflow um post com um exemplo de como resolver este problema.

Peguei este exemplo testei e funcionou. Fiz alguns pequenos ajustes e agora o exemplo funciona também em Lazarus.

Ficou interessado? Então vamos ao código!

Seguinte, para iniciar, vamos criar uma unit com o nome util.download.

Nesta unit vamos implementar uma classe que herda de TIDHttp e adicionar algumas funções que nos permita verificar o andamento do download.

Segue o código com comentários sobre as etapas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
{                                                                      }
{    TIdHTTPProgress - Extendend TIdHTTP to show progress download     }
{                                                                      }
{    Creted in https://stackoverflow.com/questions/28457925/how-to-download-a-file-with-progress-with-idhttp-via-https   }
{                                                                      }
{ Fixed and adapted to Lazarus and Delphi by Giovani Da Cruz           }
{                                                                      }
{ Please visit: https://showdelphi.com.br                              }
{----------------------------------------------------------------------}
unit util.download;
 
interface
 
uses
  Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
  IdSSLOpenSSL;
 
{$M+}
 
type
  TIdHTTPProgress = class(TIdHTTP)
  private
    FProgress: Integer;
    FBytesToTransfer: Int64;
    FOnChange: TNotifyEvent;
    IOHndl: TIdSSLIOHandlerSocketOpenSSL;
    procedure HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
    procedure HTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    procedure HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
    procedure SetProgress(const Value: Integer);
    procedure SetOnChange(const Value: TNotifyEvent);
  public
    constructor Create(AOwner: TComponent);
    procedure DownloadFile(const aFileUrl: string; const aDestinationFile: String);
  published
    property Progress: Integer read FProgress write SetProgress;
    property BytesToTransfer: Int64 read FBytesToTransfer;
    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
  end;
 
implementation
 
uses
  Sysutils;
 
{ TIdHTTPProgress }
 
constructor TIdHTTPProgress.Create(AOwner: TComponent);
begin
  inherited;
  IOHndl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  Request.BasicAuthentication := True;
  HandleRedirects := True;
  IOHandler := IOHndl;
  ReadTimeout := 30000;
 
  { Compatibilidade com lazarus }
  {$IFDEF FPC}
  OnWork := @HTTPWork;
  OnWorkBegin := @HTTPWorkBegin;
  OnWorkEnd := @HTTPWorkEnd;
  {$ELSE}
  OnWork := HTTPWork;
  OnWorkBegin := HTTPWorkBegin;
  OnWorkEnd := HTTPWorkEnd;
  {$ENDIF}
end;
 
procedure TIdHTTPProgress.DownloadFile(const aFileUrl: string; const aDestinationFile: String);
var
  LDestStream: TFileStream;
  aPath: String;
begin
  Progress := 0;
  FBytesToTransfer := 0;
  aPath := ExtractFilePath(aDestinationFile);
  if aPath <> '' then
    ForceDirectories(aPath);
 
  LDestStream := TFileStream.Create(aDestinationFile, fmCreate);
  try
    Get(aFileUrl, LDestStream);
  finally
    FreeAndNil(LDestStream);
  end;
end;
 
procedure TIdHTTPProgress.HTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  { Evento interno responsável por informar o progresso atual }
  if BytesToTransfer = 0 then // No Update File
    Exit;
 
  Progress := Round((AWorkCount / BytesToTransfer) * 100);
end;
 
procedure TIdHTTPProgress.HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  FBytesToTransfer := AWorkCountMax;
end;
 
procedure TIdHTTPProgress.HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
begin
  FBytesToTransfer := 0;
  Progress := 100;
end;
 
procedure TIdHTTPProgress.SetOnChange(const Value: TNotifyEvent);
begin
  FOnChange := Value;
end;
 
procedure TIdHTTPProgress.SetProgress(const Value: Integer);
begin
  FProgress := Value;
  if Assigned(FOnChange) then
    FOnChange(Self);
end;
 
end.

Note que o código fonte acima já está ajustado para poder ser utilizado tanto em Delphi quanto em Lazarus.

Show de bola! Agora que já temos a nossa nova classe, vamos precisar utiliza-la.
Para isso vamos ao exemplo de um botão de download em um formulário.

Vamos ao exemplo de como baixar monitorando o progresso!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{ Botão que efetua o download }
procedure TForm1.bDownloadClick(Sender: TObject);
var
  IdHTTPProgress : TIdHTTPProgress;
begin
 
  IdHTTPProgress := TIdHTTPProgress.Create(Self);
 
  try
    {$IFDEF FPC}
    IdHTTPProgress.OnChange := @ProgressOnChange;
    IdHTTPProgress.OnWorkEnd := @WorkEnd;
    {$ELSE}
    IdHTTPProgress.OnChange := ProgressOnChange;
    IdHTTPProgress.OnWorkEnd := WorkEnd;
    {$ENDIF}
 
    IdHTTPProgress.DownloadFile(edURL.Text, edFile.Text + edArq.Text);
  finally
    FreeAndNil(IdHTTPProgress);
  end;
end;

Mas só isso? Sim é realmente só isso, mas repare que no exemplo acima estou setando dois eventos para o objeto: “ProgressOnChange” e “WorkEnd”. Estes são os eventos que fazem a atualização da barra de progresso e que avisam quando o download foi concluído.

Então vamos aos códigos dos eventos:
Primeiro do evento para monitorar o progresso:

1
2
ProgressBar1.Position := TIdHTTPProgress(Sender).Progress;
  Application.ProcessMessages;

Agora o evento que avisa quando o download foi concluído.

1
2
3
4
5
procedure TForm1.WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  ProgressBar1.Position := 100;
  ShowMessage('Concluído!');
end;

Pronto, temos tudo para baixar arquivos com monitoramento do andamento do processo!

Para ajudar no entendimento, assista o vídeo abaixo que explica o código deste post.

Também deixamos a unit em um repositório no Github: https://github.com/infussolucoes/IDHttpProgress

Certo pessoal, espero que tenham gostado, lembrando que para dúvidas ou sugestões, utilizem os comentários.

Um abraço e até a próxima. Valeu!

Facebook Comments Box
  • Giovani Da Cruz
  • 8.401 views
  • 2 comentários
  • 22 de setembro de 2019

Está gostando do conteúdo? Considere pagar um cafezinho para nossa equipe!

2 respostas para “Como fazer Download de Arquivos com Progresso do andamento?”

  1. Mário Reis disse:

    Tentei repeti todos os passos.Tentei compilar dá erro!?
    Addicionei o IdComponent, continuo a não conseguir!?
    O que perdi

  2. Qual erro que você está tendo Mário?

Deixe um comentário

Ir ao topo

© 2024 Infus Soluções em Tecnologia - Todos os Direitos Reservados