I have a Delphi 10.1 Berlin Datasnap Server, that can\'t return Data packets (through a TStream) bigger than around 260.000 bytes.
I have programmed it following the
I have coded a workaround. Seeing that I can't pass data bigger than 255Kb then I split it in different 255Kb packets and send them separately (I have also added compression to minimize the bandwidth and roundtrips).
On the server I have changed StremGet to two different calls : StreamGet and StreamGetNextPacket.
function TServerMethods.StreamGet(var Complete: boolean): TStream;
var Data: TMemoryStream;
Compression: TZCompressionStream;
begin
try
// Opening Data
qCustomers.Close;
qCustomers.Open;
qOrders.Close;
qOrders.Open;
// Compressing Data
try
if Assigned(CommStream) then FreeAndNil(CommStream);
CommStream := TMemoryStream.Create;
Data := TMemoryStream.Create;
Compression := TZCompressionStream.Create(CommStream);
FDSchemaAdapter.SaveToStream(Data, TFDStorageFormat.sfBinary);
Data.Position := 0;
Compression.CopyFrom(Data, Data.Size);
finally
Data.Free;
Compression.Free;
end;
// Returning First 260000 bytes Packet
CommStream.Position := 0;
Result := TMemoryStream.Create;
Result.CopyFrom(CommStream, Min(CommStream.Size, 260000));
Result.Position := 0;
// Freeing Memory if all sent
Complete := (CommStream.Position = CommStream.Size);
if Complete then FreeAndNil(CommStream);
except
raise;
end;
end;
function TServerMethods.StreamGetNextPacket(var Complete: boolean): TStream;
begin
// Returning the rest of 260000 bytes Packets
Result := TMemoryStream.Create;
Result.CopyFrom(CommStream, Min(CommStream.Size - CommStream.Position, 260000));
Result.Position := 0;
// Freeing Memory if all sent
Complete := (CommStream.Position = CommStream.Size);
if Complete then FreeAndNil(CommStream);
end;
CommStream: TStream is declared as private on TServerMethods.
And the Client retrieves it this way :
procedure TClientForm.GetTables;
var Complete: boolean;
Input: TStringStream;
Data: TMemoryStream;
Decompression: TZDecompressionStream;
begin
Input := nil;
Data := nil;
Decompression := nil;
try
// Get the First 260000 bytes Packet
spStreamGet.ExecProc;
Input := TStringStream.Create(spStreamGet.ParamByName('ReturnValue').AsBlob);
Complete := spStreamGet.ParamByName('Complete').AsBoolean;
// Get the rest of 260000 bytes Packets
while not Complete do begin
spStreamGetNextPacket.ExecProc;
Input.Position := Input.Size;
Input.WriteBuffer(TBytes(spStreamGetNextPacket.ParamByName('ReturnValue').AsBlob), Length(spStreamGetNextPacket.ParamByName('ReturnValue').AsBlob));
Complete := spStreamGetNextPacket.ParamByName('Complete').AsBoolean;
end;
// Decompress Data
Input.Position := 0;
Data := TMemoryStream.Create;
Decompression := TZDecompressionStream.Create(Input);
Data.CopyFrom(Decompression, 0);
Data.Position := 0;
// Load Datasets
DataModuleFDClient.FDSchemaAdapter.LoadFromStream(Data, TFDStorageFormat.sfBinary);
finally
if Assigned(Input) then FreeAndNil(Input);
if Assigned(Data) then FreeAndNil(Data);
if Assigned(Decompression) then FreeAndNil(Decompression);
end;
end;
It works fine now.