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
@Marc: I think Henrikki meant a single function, not a single function call...
I've modified your code so that only one function is enough and so that projects with different SchemaAdapters/StoredProcedures can be used.
The maximum streamsize is declared as a constant (MaxDataSnapStreamSize) and is set to $F000, wich is the MaxBuffSize a TStream.CopyFrom function handles (see System.Classes).
FComprStream is a private field of type TMemorySTream, taken care of in the constructor and destructor of the servermodule.
On the server side:
const
MaxDataSnapStreamSize = $F000;
function TServerMethods1.StreamGet(const aFDSchemaAdapter: TFDSchemaAdapter; var aSize: Int64): TStream;
var
lZIPStream: TZCompressionStream;
lDataStream: TMemoryStream;
I: Integer;
lMinSize: Int64;
begin
if aSize=-1 then
exit;
lDataStream:=TMemoryStream.Create;
try
if aSize=0 then
begin
FComprStream.Clear;
with aFDSchemaAdapter do
for I := 0 to Count-1 do
begin
DataSets[I].Close;
DataSets[I].Open;
end;
lZIPStream := TZCompressionStream.Create(TCompressionLevel.clFastest, FComprStream);
try
aFDSchemaAdapter.SaveToStream(lDataStream, TFDStorageFormat.sfBinary);
lDataStream.Position := 0;
lZIPStream.CopyFrom(lDataStream, lDataStream.Size);
finally
lDataStream.Clear;
lZIPStream.Free;
end;
lMinSize:=Min(FComprStream.Size, MaxDataSnapStreamSize);
FComprStream.Position:=0;
end
else
lMinSize:=Min(aSize, MaxDataSnapStreamSize);
lDataStream.CopyFrom(FComprStream, lMinSize);
lDataStream.Position := 0;
aSize:=FComprStream.Size-FComprStream.Position;
Result:=lDataStream;
if aSize=0 then
FComprStream.Clear;
except
aSize:=-1;
lDataStream.Free;
raise;
end;
end;
On the client side:
procedure TdmClientModuleDS.GetTables(const aStPrGet: TFDStoredProc; const aFDSchemaAdapter: TFDSchemaAdapter);
var
lSize: Int64;
lZIPStream: TStringStream;
lDataStream: TMemoryStream;
lUNZIPStream: TZDecompressionStream;
I: Integer;
begin
try
lSize:=0;
for I := 0 to aFDSchemaAdapter.Count-1 do
aFDSchemaAdapter.DataSets[I].Close;
aStPrGet.ParamByName('aSize').AsInteger:=0;
aStPrGet.ExecProc;
lZIPStream:=TStringStream.Create(aStPrGet.ParamByName('ReturnValue').AsBlob);
lSize:=aStPrGet.ParamByName('aSize').AsInteger;
while lSize>0 do
with aStPrGet do
begin
ParamByName('aSize').AsInteger:=lSize;
ExecProc;
lZIPStream.Position:=lZIPStream.Size;
lZIPStream.WriteBuffer(TBytes(ParamByName('ReturnValue').AsBlob),Length(ParamByName('ReturnValue').AsBlob));
lSize:=ParamByName('aSize').AsInteger;
end;
lZIPStream.Position:=0;
lDataStream:=TMemoryStream.Create;
lUNZIPStream:=TZDecompressionStream.Create(lZIPStream);
lDataStream.CopyFrom(lUNZIPStream, 0);
lDataStream.Position:=0;
aFDSchemaAdapter.LoadFromStream(lDataStream,TFDStorageFormat.sfBinary);
finally
if Assigned(lZIPStream) then
FreeAndNil(lZIPStream);
if Assigned(lDataStream) then
FreeAndNil(lDataStream);
if Assigned(lUNZIPStream) then
FreeAndNil(lUNZIPStream);
end;
end;