



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!
Você precisa fazer o login para publicar um comentário.
Tentei repeti todos os passos.Tentei compilar dá erro!?
Addicionei o IdComponent, continuo a não conseguir!?
O que perdi
Qual erro que você está tendo Mário?