Search code examples
delphiindyidhttp

Delphi: Use TidHTTPServer for transfer file and monitoring byte send for single request


Using TIdHTTPServer (Indy 10.6), how do track how many bytes are sent to the client (user browser) for each request (on close connection)?

procedure onCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
begin
    AResponseInfo.ContentStream := TFileStream.Create('C:/HugeFile.zip', fmOpenRead or fmShareCompat);
    AResponseInfo.ContentLength := AResponseInfo.ContentStream.Size;
    AResponseInfo.WriteHeader;
    AResponseInfo.WriteContent;
    AResponseInfo.ContentStream.Free;
    AResponseInfo.ContentStream := nil;
end;

eg, in a log file:

2014-11-06 20:32:00 - IPAddress 84.XXX.XXX.XXX download 1000000 Bytes (100%)
2014-11-05 16:05:00 - IPAddress 72.XXX.XXX.XXX download 500000  Bytes (50%)

Solution

  • If you just want to output a log at the end of the transfer saying how many bytes were sent, you can derive a new class from TFileStream and override its destructor to output a log message showing the stream's current Position relative to its Size. Whatever other information you need to log can be passed to the constructor and saved so the destructor can use it.

    For example:

    type
      TMyFileStream = class(TFileStream)
      private
        FContext: TIdContext;
      public
        constructor Create(const AFileName: string; AContext: TIdContext);
        destructor Destroy; override;
      end;
    
    constructor TMyFileStream.Create(const AFileName: string; AContext: TIdContext);
    begin
      inherited Create(AFileName, fmOpenRead or fmShareCompat);
      FContext := AContext;
    end;
    
    destructor TMyFileStream.Destroy;
    var
      LPos, LSize: Int64;
      LPercent: Integer;
    begin
      LPos := Position;
      LSize := Size;
      if LSize <> 0 then
        LPercent := (LPosition * 100) div LSize
      else
        LPercent := 100;
      MyLogFile.WriteLine(Format('%s IPAddress %s download %d Bytes (%d%%)', [FormatDateTime('YYYY-MM-DD HH:NN:SS', Now), AContext.Binding.PeerIP, LPos, LPercent]);
      inherited;
    end;
    
    procedure onCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
    begin
      AResponseInfo.ContentStream := TMyFileStream.Create('C:/HugeFile.zip', AContext);
    end;