unit uChunkUploaderThread;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls,

  // my Units
  uMain_TPS_ChunkUploader,
  uExampleMain;

type
  TChunkUploaderThread = class(TThread)

  private

    FExampleMain:TfExampleMain;
    FFileName:string;
    FChunkSize:Int64;

    FFileSizeUploadInChunks:Int64;
    FFileSizeDivideInChunks:Int64;

    fEx : Exception;
    procedure QueryError;

    procedure OnDivideInChunksOnClient(Sender: TObject; ACountOfBytes: Int64);
    procedure OnDivideInChunksOnClientBegin(Sender: TObject; ACountOfBytes: Int64);
    procedure OnGatherChunksOnServer(Sender: TObject; ACountOfBytes: Int64);
    procedure OnUploadInChunks(Sender: TObject; ACountOfBytes: Int64);
    procedure OnUploadInChunksBegin(Sender: TObject; ACountOfBytes: Int64);
    procedure OnUploadInChunksEnd(Sender: TObject; ACountOfBytes: Int64);

  public

  PS_ChunkUploader: TPS_ChunkUploader;

  property ExampleMain:TfExampleMain read FExampleMain write FExampleMain;
  property FileName:string read FFileName write FFileName;
  property ChunkSize:Int64 read FChunkSize write FChunkSize;




  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 TChunkUploaderThread.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.
    
}

{ TChunkUploaderThread }

procedure TChunkUploaderThread.Execute;
begin
  NameThreadForDebugging('ChunkUploaderThread_SomeName');
  { Place thread code here }

PS_ChunkUploader:=TPS_ChunkUploader.Create(nil);

try

   try

        ExampleMain.CS.Enter;

         with PS_ChunkUploader.VisualFrame_TPS_ChunkUploader do begin


              with HTTP_ConnectionParams do begin

              Protocol:='http';
              Host:='localhost';//'40.85.142.196';//'192.168.1.102';//'localhost';
              Port:='40000';
              IdUser:='1'; // << Critical important to use ID that are in DataBase coffeetest.users
              User:='SomeUser';

              DefineServerToRequest();

              end;


          // works much faster without setting HTTPRequests.IdHTTP.ConnectTimeout
          //  HTTPRequests.IdHTTP.ConnectTimeout:=5*60000; // 5 minutes for big files

          HTTPRequests.IdHTTP.ReadTimeout:=5*60000;  // 5 minutes for big files

         end;



        with PS_ChunkUploader.VisualFrame_TPS_ChunkUploader.SendFileInChunks do begin


        //assign Events
        OnDivideInChunksOnClientBegin:=Self.OnDivideInChunksOnClientBegin;
        OnDivideInChunksOnClient:=Self.OnDivideInChunksOnClient;
        OnUploadInChunksBegin:=Self.OnUploadInChunksBegin;
        OnUploadInChunks:=Self.OnUploadInChunks;
        OnGatherChunksOnServer:=Self.OnGatherChunksOnServer;
        OnUploadInChunksEnd:=Self.OnUploadInChunksEnd;

        //send File In Chunks
        SendFileInChunks(FFileName,FChunkSize);

        end;


    except

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

    end;

finally

PS_ChunkUploader.Free;
ExampleMain.CS.Leave;

end;



end;




//

procedure TChunkUploaderThread.OnDivideInChunksOnClientBegin(Sender: TObject; ACountOfBytes: Int64);
begin

    Synchronize(
      procedure
      begin


       with ExampleMain do begin

        ProgressBar.Position:=0;
        ProgressBar.Max:=100;
        FFileSizeDivideInChunks:=ACountOfBytes;

        Memo.Lines.add('OnDivideInChunksOnClientBegin');
        end;


      end
      );





end;


procedure TChunkUploaderThread.OnDivideInChunksOnClient(Sender: TObject; ACountOfBytes: Int64);

begin


    Synchronize(
      procedure
      begin


        with ExampleMain do begin

        ProgressBar.Position:=Trunc( (ACountOfBytes/FFileSizeDivideInChunks)*100);
        Memo.Lines.add('OnDivideInChunksOnClient '+ProgressBar.Position.ToString+' %');

        end;

      end
      );




end;




procedure TChunkUploaderThread.OnUploadInChunksBegin(Sender: TObject; ACountOfBytes: Int64);
begin



    Synchronize(
      procedure
      begin


       with ExampleMain do begin

      ProgressBar.Position:=0;
      ProgressBar.Max:=100;
      FFileSizeUploadInChunks:=ACountOfBytes;
      Memo.Lines.add('OnUploadInChunksBegin');

      end;

      end
      );




end;

procedure TChunkUploaderThread.OnUploadInChunks(Sender: TObject; ACountOfBytes: Int64);


begin


    Synchronize(
      procedure
      begin


        with ExampleMain do begin


        ProgressBar.Position:=Trunc( (ACountOfBytes/FFileSizeUploadInChunks)*100);
        Memo.Lines.add('OnUploadInChunks '+ProgressBar.Position.ToString()+' %');

        end;


      end
      );




end;




procedure TChunkUploaderThread.OnUploadInChunksEnd(Sender: TObject; ACountOfBytes: Int64);


begin


    Synchronize(
      procedure
      begin

         ExampleMain.Memo.Lines.add('Successfully uploaded');
         showmessage('Successfully uploaded');

      end
      );




end;



procedure TChunkUploaderThread.QueryError;
begin
Application.OnException( Self, fEx );
end;

procedure TChunkUploaderThread.OnGatherChunksOnServer(Sender: TObject; ACountOfBytes: Int64);
begin
//


    Synchronize(
      procedure
      begin

        with ExampleMain do begin

        Memo.Lines.add('OnGatherChunksOnServer Wait some time...');

        end;


      end
      );





end;



end.
