Download a File from internet programmatically with an Progress event using Delphi and Indy
Asked Answered
M

1

18

I need a way to download a file from the Internet using Delphi via HTTP, Which include an Progress event, I'm looking for a method which uses the Indy components.

I am using Delphi 7.

Masbate answered 2/2, 2010 at 13:55 Comment(0)
B
25

I've coded this example, using just one HTTP GET, with Indy 10, hope it works with Indy 9 too:

uses
  {...} IdHTTP, IdComponent;

type
  TFormMain = class(TForm)
    {...}
  private
    {...}
    procedure HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
  end;
{...}

procedure TFormMain.Button1Click(Sender: TObject);
var
  Http: TIdHTTP;
  MS: TMemoryStream;
begin
  Http := TIdHTTP.Create(nil);
  try
    MS := TMemoryStream.Create;
    try
      Http.OnWork:= HttpWork;

      Http.Get('http://live.sysinternals.com/ADExplorer.exe', MS);
      MS.SaveToFile('C:\ADExplorer.exe');

    finally
      MS.Free;
    end;
  finally
    Http.Free;
  end;
end;

procedure TFormMain.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  Http: TIdHTTP;
  ContentLength: Int64;
  Percent: Integer;
begin
  Http := TIdHTTP(ASender);
  ContentLength := Http.Response.ContentLength;

  if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and
     (ContentLength > 0) then
  begin
    Percent := 100*AWorkCount div ContentLength;

    MemoOutput.Lines.Add(IntToStr(Percent));
  end;
end;
Banderilla answered 2/2, 2010 at 15:42 Comment(6)
The Response.ContentLength value is not always valid. In particular, in HTTP 1.1 replies that use the "chunked" transfer encoding, the "Content-Length" header is not allowed to be used. During chunked transfers, the total size of the data is not known ahead of time, as the data is transmitted in multiple blocks, and each block has its own size internally.Contrapuntal
Better? Now I use exactly the same conditions as in TIdCustomHTTP.ReadResult() inside the IdHTTP.pas unitBanderilla
and don't forget to write Application.ProcessMessages(); on OnWork event!Mayest
Don't use Application.ProcessMessages(). That will pump the message queue for ALL pending messages, which can cause side effects and reentry problems if you are not careful. Better to use the TForm.Update() method instead to process only pending paint messages and no others.Contrapuntal
Rather than avoiding Application.ProcessMessages(), design your application such that it can handle receiving messages during a file download. This can be accomplished by moving the download code into a thread (but you now have two porbelms!), or by using Application.ProcessMessages() and working through the possible cases (button clicks, window close, etc) to prevent re-entrancy problems -- often the easiest way is a dedicated download dialog. If you use just TForm.Update(), you will cause your application to be non-responsive to user interaction.Armed
Can it download files from https? Cause I get an "IOHandler value is not valid" error for https sites...Phonetist

© 2022 - 2024 — McMap. All rights reserved.