Delphi download multithreading

1.6k views Asked by At

My initial question was misleading, I'll try to improve it:

I was able to write a small delphi programme, which is able to do a threaded download by using indy's idHTTP. It consists of 2 files:

  • the form:

    interface
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Label1: TLabel;
        Button2: TButton;
        IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
        IdAntiFreeze1: TIdAntiFreeze;
        IdHTTP: TIdHTTP;
        ProgressBar1: TProgressBar;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
         procedure UpdateLabel(BytesDone: Integer);
         procedure UpdateProgressBar(AWorkCount: Int64);
         procedure InitProgressBar(AWorkCountMax: Int64);
         procedure ResetProgressBar;
      end;
    
    var
      Form1: TForm1;
      uStopDownloading: Boolean;
    
    implementation
    
    {$R *.dfm}
    
    uses Unit2;
    
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      HTTPThread: TIdHTTPThread;
    begin
      HTTPThread := TIdHTTPThread.Create(True);
      HTTPThread.Url := 'https://www.bot-factory.de/tmp/lorem7.txt';
      HTTPThread.EncodedStr := '';
      HTTPThread.Filename := 'C:\test.txt';
      HTTPThread.FreeOnTerminate := True;
      HTTPThread.Resume;
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
     idhttp.Disconnect;
    end;
    
    procedure TForm1.UpdateLabel(BytesDone: Integer);
    begin
      Label1.caption := format('%.0n',[extended(BytesDone+0.0)]) +' bytes loaded.';
    end;
    
    procedure TForm1.UpdateProgressBar(AWorkCount: Int64);
    begin
      ProgressBar1.Position := AWorkCount;
    end;
    
    procedure TForm1.InitProgressBar(AWorkCountMax: Int64);
    begin
      Screen.Cursor := crHourGlass;
      ProgressBar1.Max := AWorkCountMax;
      ProgressBar1.Position := 0;
    end;
    
    procedure TForm1.ResetProgressBar;
    begin
     Screen.Cursor := crDefault;
     showmessage('Job is done');
    end;
    
    END.
    
  • And the Thread-Unit:

    interface
    
    uses
      Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, sysutils;
    
    type
      TIdHTTPThread = class(TThread)
      private
        FURL: AnsiString;
        FencodedStr: string;
        FFilename: AnsiString;
        FBytesDone,FProgress,FWorkCountMax: Int64;
        IdHTTP: TIdHTTP;
        procedure OnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
        procedure OnWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
        procedure OnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
        procedure Updatelabel;
        procedure UpdateProgressBar;
        procedure InitProgressBar;
        procedure ResetProgressBar;
        procedure Disconnect;
      public
        Constructor Create(CreateSuspended: Boolean);
        Destructor Destroy; override;
        property Url: AnsiString read FURL write FUrl;
        property encodedstr: String read FencodedStr write FencodedStr;
        property Filename: AnsiString read FFilename write FFilename;
      protected
        procedure Execute; override;
      end;
    
    implementation
    
    uses
      Unit1; // Formular Unit
    
    constructor TIdHTTPThread.Create(CreateSuspended: Boolean);
    begin
      inherited Create(Suspended);
      IdHTTP := TIdHTTP.Create;
      IdHTTP.OnWork := OnWork;
      IdHTTP.OnWorkBegin := OnWorkBegin;
      IdHTTP.OnWorkEnd := OnWorkEnd;
      //IdHTTP.Disconnect := Disconnect;
    end;
    
    destructor TIdHTTPThread.Destroy;
    begin
      IdHTTP.Free;
      inherited;
    end;
    
    procedure TIdHTTPThread.Execute;
    var
      DestStream: TFileStream;
    begin
      DestStream := TFileStream.Create(Filename, fmCreate);
      try
        IdHTTP.Get(Url, DestStream);
      finally
        DestStream.Free;
      end;
    end;
    
    procedure TIdHTTPThread.OnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    begin
      FBytesDone := AWorkCount;
      FProgress := AWorkCount;
      Synchronize(Updatelabel);
      Synchronize(UpdateProgressBar);
    end;
    
    procedure TIdHTTPThread.OnWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
    begin
      FWorkCountMax := AWorkCountMax;
      Synchronize(InitProgressBar);
    end;
    
    procedure TIdHTTPThread.Disconnect;
    begin
      idhttp.Disconnect;
    end;
    
    procedure TIdHTTPThread.OnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
    begin
      Synchronize(ResetProgressBar);
    end;
    
    procedure TIdHTTPThread.Updatelabel;
    begin
      Form1.UpdateLabel(FBytesDone);
    end;
    
    procedure TIdHTTPThread.UpdateProgressBar;
    begin
      Form1.UpdateProgressBar(FProgress);
    end;
    
    procedure TIdHTTPThread.InitProgressBar;
    begin
      Form1.initProgressBar(FWorkCountMax);
    end;
    
    procedure TIdHTTPThread.resetProgressBar;
    begin
      Form1.resetProgressBar;
    end;
    
    END.
    

I have in fact 2 questions:

  1. How can I interrupt the download of a (large) file ? I know that idhttp.disconnect should do the trick, but I do not know how to use it properly in my thread.
  2. And furthermore: how can I use POST instead of GET?

I need to run this POST in a thread:

{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//submit_post
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
Procedure submit_post(url_string,EncodedStr,filename:string);
var
  aStream: TMemoryStream;
  Params: TStringStream;
begin
  astream := TMemoryStream.create;
  Params := TStringStream.create('');
  Form1.IdHTTP.Request.Clear;
  Form1.IdHTTP.HandleRedirects := TRUE;

  try
    with Form1.IdHTTP do
    begin
      Params.WriteString(EncodedStr);
      Request.ContentType := 'application/x-www-form-urlencoded';
      Request.Charset := 'utf-8';
      try
        Response.KeepAlive := False;
        Post(url_string, params, astream);
      except
        on E: Exception do
        begin
          exit;
        end;
      end;
    end;
    astream.WriteBuffer(#0' ', 1);
    astream.Position := 0;
    astream.SaveToFile(filename);
  finally
    astream.Free;
    Params.Free;
  end;
end;
0

There are 0 answers