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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Salvador
  • 16,132
  • 33
  • 143
  • 245

1 Answers1

26

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;
ulrichb
  • 19,610
  • 8
  • 73
  • 87
  • 2
    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. – Remy Lebeau Feb 04 '10 at 02:47
  • 1
    Better? Now I use exactly the same conditions as in `TIdCustomHTTP.ReadResult()` inside the `IdHTTP.pas` unit – ulrichb Feb 04 '10 at 14:11
  • 2
    and don't forget to write `Application.ProcessMessages();` on OnWork event! – Suhrob Samiev Dec 03 '11 at 05:37
  • 10
    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. – Remy Lebeau Jan 07 '12 at 09:22
  • 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. – Marc Durdin Jul 05 '20 at 22:02
  • Can it download files from https? Cause I get an "IOHandler value is not valid" error for https sites... – Gabriel Feb 10 '22 at 20:27