John Rosenberg
John Rosenberg

Reputation: 617

Indy upload speed

From this code, how can I return the upload speed?

procedure TForm1.Button1Click(Sender: TObject);
begin

ftp.Host := 'domain';
ftp.Username := 'username';
ftp.password := 'password';
ftp.Connect;
ftp.Put('random-filename.ext'); //This is where it should grab only the latest file
//label1.caption := 'Download Speed: %s';  
ftp.Quit;
ftp.Disconnect;

end;

Would a timer be necessary?

Thanks.

Upvotes: 2

Views: 1701

Answers (4)

Stéphane B.
Stéphane B.

Reputation: 3280

No TTimer class is necessary, only Indy component OnWorkBegin, OnWork and OnWorkEnd events.

You can do like below but I recommend you to put FTP code in a thread and to update user interface with the Synchronize method for best performance.

interface 

uses
  // ...
  Windows;

type
  TForm1 = class(TForm)
  private
    startWriteTime : DWord;
    byteToWrite : Int64;

    procedure ftp_OnWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
    procedure ftp_OnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    procedure ftp_OnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);

    procedure displayWriteSpeed(byteWritten: Int64);
end;

implementation

uses
  // ...
  SysUtils;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ftp.OnWorkBegin := ftp_OnWorkBegin;
  ftp.OnWork := ftp_OnWork;
  ftp.OnWorkEnd := ftp_OnWorkEnd;
  // ...
  ftp.Connect;
  // ...
end;

procedure TForm1.ftp_OnWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  if AWorkMode = wmWrite then
  begin
    byteToWrite := AWorkCountMax;
    startWriteTime := Windows.GetTickCount;
    displayWriteSpeed(-1);
  end;
end;

procedure TForm1.ftp_OnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  if AWorkMode = wmWrite then
  begin
    displayWriteSpeed(AWorkCount);
  end;
end;

procedure TForm1.ftp_OnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  if AWorkMode = wmWrite then
  begin
    displayWriteSpeed(byteToWrite);
  end;
end;

procedure TForm1.displayWriteSpeed(byteWritten: Int64);
var
  elapsedMilliSeconds,  elapsedSeconds : Dword;
  speedBytesPerSeconds : Int64;
begin
  if byteWritten < 0 then
  begin
    {writeSpeedLabel.}Caption := 'upload speed: ?';
    Exit;
  end;

  elapsedMilliSeconds := Windows.GetTickCount - startWriteTime;
  elapsedSeconds := elapsedMilliSeconds div 1000;
  speedBytesPerSeconds := byteWritten div elapsedSeconds;
  {writeSpeedLabel.}Caption := SysUtils.Format('upload speed: %d b/s', [speedBytesPerSeconds ] );
end;

Upvotes: 1

Marcus Adams
Marcus Adams

Reputation: 53870

For the timer part:

You can use the built in functions and global variables:

var
  start, stop, elapsed: TDateTime;
  ielapsed: Integer;

// Start the timer
start := Now;
// Stop the timer
stop := Now;
elapsed := stop - start;
// Convert to milliseconds
ielapsed := round(elapsed * 60 * 60 * 24 * 1000);

Since the Windows API function GetTickCount is already in milliseconds, it's an easy way to calculate elapsed time, but only on Windows 2000+:

var
  start, stop, elapsed: DWORD;

start := GetTickCount;
stop := GetTickCount;

if (stop > start) then
begin
  elapsed := stop - start;
end
else
begin
  // Handle overflow
  elapsed := MAXDWORD - start + stop;
end;

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 597941

The TIdFTP.OnWorkBegin event will tell you how many bytes are going to be sent, and the TIdFTP.OnWork event will tell you how many bytes have been sent so far during the transfer. Based on how much time passes between individual OnWork event firings and the difference in transferred bytes between each one, you can calculate the speed.

Upvotes: 2

RRUZ
RRUZ

Reputation: 136431

Assuming you are using a TIdFTP component then you must use the OnWork, OnWorkBegin and OnWorkEnd events to calculate the transfer rate.

Upvotes: 4

Related Questions