Found a lot of articles related with this using HHTP, but bot a single one using TCP...
The OnWork events work exactly the same way in all of Indy's components.
//ClientChannel.OnWork:= ??; Whats going here?
An event handler, obviously, for example:
procedure TSomeClass.OnWorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
...
end;
var InstanceOfSomeClass: TSomeClass;
...
ClientChannel.OnWork := InstanceOfSomeClass.OnWorkHandler;
Alternatively, if you don't have an object instance to put the handler into, you can use a standalone procedure, but you will have to tweak the function signature and then use the
System.TMethod record to assign it to the event, eg:
// note the extra ASelf parameter!...
procedure OnWorkHandler(ASelf: Pointer; ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
...
end;
var
M: TMethod;
begin
M.Data := nil; // Or whatever you want the ASelf parameter to point at...
M.Code := @OnWorkHandler;
ClientChannel.OnWork := TWorkEvent(M);
end;
Or:
var
Evt: TWorkEvent;
begin
TMethod(Evt).Data := nil; // Or whatever you want the ASelf parameter to point at...
TMethod(Evt).Code := @OnWorkHandler;
ClientChannel.OnWork := Evt;
end;
Note, you will also need a handler for the
OnWorkBegin event, too. The
OnWork event only tells you how many bytes have been transferred so far, but the
OnWorkBegin event tells you how many bytes are expected, if known up front:
procedure TSomeClass.OnWorkBeginHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
...
end;
var InstanceOfSomeClass: TSomeClass;
...
ClientChannel.OnWorkBegin := InstanceOfSomeClass.OnWorkBeginHandler;
Or:
// note the extra ASelf parameter!...
procedure OnWorkBeginHandler(ASelf: Pointer; ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
...
end;
var
M: TMethod;
begin
M.Data := nil; // Or whatever you want the ASelf parameter to point at...
M.Code := @OnWorkBeginHandler;
ClientChannel.OnWorkBegin := TWorkBeginEvent(M);
end;
Or:
var
Evt: TWorkBeginEvent;
begin
TMethod(Evt).Data := nil; // Or whatever you want the ASelf parameter to point at...
TMethod(Evt).Code := @OnWorkBeginHandler;
ClientChannel.OnWorkBegin := Evt;
end;
ClientChannel.IOHandler.ReadStream(AFileStream);
The default parameters of
ReadStream() are
AByteCount=-1 and
AReadUntilDisconnect=False. Under that specific combination,
ReadStream() will first attempt to read an integer from the connection, indicating the stream's total byte size, before then reading that many bytes for the actual stream data. That byte count will be passed to the
OnWorkBegin event, and is expected to be transmitted as either a 4-byte
Integer or an 8-byte
Int64 depending on the IOHandler's
LargeStream property.
This has worked for me for years, but now i need be able to "follow" the progress of the download (maybe a percentage of the completed download?) to be able to abort it (and also in case the user closes the app during a long download)
Being able to calculate a percentage requires knowing how many bytes are actually in the file to begin with. Is your server sending that byte count up front?