unit uDownLoadFileThread;

interface

uses

  Winapi.Windows,  Winapi.Messages,  System.SysUtils,  System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,  Vcl.Dialogs,  Vcl.StdCtrls,
  Vcl.ComCtrls,  Vcl.ExtCtrls,  System.ImageList,  Vcl.ImgList,
  IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP,

  uVisualFrame,uDiminishPicSize,System.NetEncoding;


type
  TDownloadFileThread = class(TThread)
  private
    { Private declarations }

    FVisualFrame_HTTP:TVisualFrame_HTTP;
    FLink:string;

    FWorkCountMax:Int64;

    FSaveFileName:string;

    fEx : Exception;
    procedure QueryError;

    procedure OnWorkBegin(ASender:TObject;AWorkMode:TWorkMode; AWorkCountMax:Int64);
    procedure OnWork(ASender:TObject;AWorkMode:TWorkMode; AWorkCount:Int64);

  public

    property VisualFrame_HTTP:TVisualFrame_HTTP read FVisualFrame_HTTP
    write FVisualFrame_HTTP;

    property Link:String read FLink write FLink;

    property SaveFileName:string
    read FSaveFileName write FSaveFileName;


  protected
    procedure Execute; override;
  end;

implementation

{ 
  Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);  

  and UpdateCaption could look like,

    procedure TDownloadThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; 
    
    or 
    
    Synchronize( 
      procedure 
      begin
        Form1.Caption := 'Updated in thread via an anonymous method' 
      end
      )
    );
    
  where an anonymous method is passed.
  
  Similarly, the developer can call the Queue method with similar parameters as 
  above, instead passing another TThread class as the first parameter, putting
  the calling thread in a queue with the other thread.
    
}

{ TDownloadThread }

procedure TDownloadFileThread.Execute;

var RelativeLink:String;
    AbsoluteLink:String;

    FileStream: TFileStream;



begin
  { Place thread code here }

with FVisualFrame_HTTP do begin

 CSDownloadFile.Enter;



    FileStream:=TFileStream.Create(SaveDialog.FileName,fmCreate);

  try

      try
      //

           //Preparing Link
           RelativeLink:=Link;
           RelativeLink:=RelativeLink.Substring(1);
           RelativeLink:=TNetEncoding.URL.Encode(RelativeLink);


           IdHTTPDownloadFile.OnWorkBegin:=OnWorkBegin;
           IdHTTPDownloadFile.OnWork:=OnWork;

           AbsoluteLink:=HTTPServerToRequest+'/'+RelativeLink;


           IdHTTPDownloadFile.Get(AbsoluteLink,FileStream);


      except

            fEx := ExceptObject as Exception;
            Synchronize( QueryError );


      end;



  finally
  //

  FileStream.Free;


  CSDownloadFile.Leave;

  end;

end;


end;

procedure TDownloadFileThread.OnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin

    Synchronize(
      procedure
      begin
        VisualFrame_HTTP.ProgressBar.Position:=trunc( (AWorkCount/FWorkCountMax)*100 );
      end
      )





end;

procedure TDownloadFileThread.OnWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin

   FWorkCountMax:=AWorkCountMax;

    Synchronize(
      procedure
      begin
        VisualFrame_HTTP.ProgressBar.Max:=100;
      end
      )


//
end;

procedure TDownloadFileThread.QueryError;
begin

//
Application.OnException( Self, fEx );

end;

end.
