Can't retrieve TStreams bigger than around 260.000 bytes from a Datasnap Server

前端 未结 6 529
盖世英雄少女心
盖世英雄少女心 2020-12-11 06:05

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

6条回答
  •  不知归路
    2020-12-11 06:43

    @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;
    

提交回复
热议问题