0

I'm trying to use Indy's TIdFTPServer and need to show in the main window a summary of traffic bitrate when clients upload or download files from the server.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • `TIdFTPServer` does not natively provide that information. You would have to manually assign an Intercept component to the `TIdFTPServerContext.DataChannel.FDataChannel.Intercept` property and have it calculate the bitrate as needed. Just remember that `TIdFTPServer` is a multi-threaded component, so your calculations will have to be thread-safe, and your updates to the UI will have to be synced with the main UI thread. – Remy Lebeau Oct 29 '21 at 17:56
  • Thanks for the answer. Unfortunately, I can't understand exactly how to do this, about DataChannel I have already read and tried to add it to the idConnectionIntercept, but nothing happened. I did not find examples with the code at all, apparently no one writes FTP servers to themselves – Денис Бердяев Oct 29 '21 at 18:39
  • Have a look at [this answer](https://stackoverflow.com/a/47041899/65863), though its example is using `TIdInterceptThrottler` to throttle an FTP transfer. Since you are interested in only measuring the bitrate, you can use `TIdConnectionIntercept` instead (or write your own class derived from it). You will be given each buffer of data transferred for uploads and downloads. Simply calculate the number of bytes between events and extrapolate over time as needed. – Remy Lebeau Oct 29 '21 at 19:04

1 Answers1

0

Thanks for Remy Lebeau! Working code:

type
  TCountTrafficInterceptor = class (TIdConnectionIntercept)
  public
    type TIntPointer = ^Longint;
  private
    FTraffic : TIntPointer;
  public
    constructor Create (TrafficVar : TIntPointer);
    procedure Send (var ABuffer : TIdBytes); override;
    procedure Receive (var ABuffer : TIdBytes); override;
  end;

    PerSecondTimer: TTimer;
    EditDownloadBitrate: TEdit;
    EditUploadBitrate: TEdit;
    LabelSummaryDownload: TLabel;
    LabelSummaryUpload: TLabel;

var
  DownloadTraffic,UploadTraffic,SummaryDownload,SummaryUpload:LongInt;

procedure TForm1.IdFTPServer1RetrieveFile(ASender: TIdFTPServerContext;
  const AFileName: string; var VStream: TStream);

var Conn: TIdTCPConnection;
begin
  Conn := TIdDataChannelAccess(ASender.DataChannel).FDataChannel;
  if Conn.Intercept = nil then
    Conn.Intercept := TCountTrafficInterceptor.Create (@DownloadTraffic);
  VStream := TFileStream.Create(ReplaceChars(AppDir+AFilename),fmOpenRead);
end;

procedure TForm1.IdFTPServer1StoreFile(ASender: TIdFTPServerContext;
  const AFileName: string; AAppend: Boolean; var VStream: TStream);
var Conn: TIdTCPConnection;
begin
  Conn := TIdDataChannelAccess(ASender.DataChannel).FDataChannel;
  if Conn.Intercept = nil then
    Conn.Intercept := TCountTrafficInterceptor.Create (@UploadTraffic);

 if not Aappend then
 begin
   VStream := TFileStream.Create(ReplaceChars(AppDir+AFilename),fmCreate)
 end
 else
 begin
   VStream := TFileStream.Create(ReplaceChars(AppDir+AFilename),fmOpenWrite)
 end;

end;

procedure TForm1.PerSecondTimerTimer(Sender: TObject);
var s:string;
begin
 s:='0 B/s';
 if DownloadTraffic<=1024 then s:=IntToStr(DownloadTraffic div 1024)+'.'+IntToStr(DownloadTraffic mod 1024)+' B/s';
 if DownloadTraffic>1024 then s:=IntToStr(DownloadTraffic div 1024)+'.'+IntToStr(DownloadTraffic mod 1024)+' Kb/s';
 if DownloadTraffic>1048576 then s:=IntToStr(DownloadTraffic div 1048576)+'.'+IntToStr(DownloadTraffic mod 1048576)+' Mb/s';
 EditDownloadBitrate.Text:=s;
 SummaryDownload:=SummaryDownload+DownloadTraffic;
 s:=SummaryDownload.ToString;
 if SummaryDownload<=1024 then s:=IntToStr(SummaryDownload div 1024)+'.'+IntToStr(SummaryDownload mod 1024)+' B/s';
 if SummaryDownload>1024 then s:=IntToStr(SummaryDownload div 1024)+'.'+IntToStr(SummaryDownload mod 1024)+' Kb/s';
 if SummaryDownload>1048576 then s:=IntToStr(SummaryDownload div 1048576)+'.'+IntToStr(SummaryDownload mod 1048576)+' Mb/s';
 LabelSummaryDownload.Caption:=s;
 DownloadTraffic:=0;

 s:='0 B/s';
 if UploadTraffic<=1024 then s:=IntToStr(UploadTraffic div 1024)+'.'+IntToStr(UploadTraffic mod 1024)+' B/s';
 if UploadTraffic>1024 then s:=IntToStr(UploadTraffic div 1024)+'.'+IntToStr(UploadTraffic mod 1024)+' Kb/s';
 if UploadTraffic>1048576 then s:=IntToStr(UploadTraffic div 1048576)+'.'+IntToStr(UploadTraffic mod 1048576)+' Mb/s';
 EditUploadBitrate.Text:=s;
 SummaryUpload:=SummaryUpload+UploadTraffic;
 s:=SummaryUpload.ToString;
 if SummaryUpload<=1024 then s:=IntToStr(SummaryUpload div 1024)+'.'+IntToStr(SummaryUpload mod 1024)+' B/s';
 if SummaryUpload>1024 then s:=IntToStr(SummaryUpload div 1024)+'.'+IntToStr(SummaryUpload mod 1024)+' Kb/s';
 if SummaryUpload>1048576 then s:=IntToStr(SummaryUpload div 1048576)+'.'+IntToStr(SummaryUpload mod 1048576)+' Mb/s';
 LabelSummaryUpload.Caption:=s;
 UploadTraffic:=0;

end;