0

All,

I am working on a new datasnap project based on the example project located in C:\Users\Public\Documents\Embarcadero\Studio\18.0\Samples\Object Pascal\DataSnap\FireDAC_DBX.

I am trying to transfer a large stream (1,606,408 bytes) from datasnap server to client. I am running into what appears to be a common issue and that is that the entire stream does not make it to the client.

Here is my server code:

//Returns Customer Info
function TServerMethods.GetBPInfo(CardCode : String): TStringStream;
begin
  Result := TStringStream.Create;
  try
    qBPInfo.Close;
    if CardCode.Trim = '' then
       qBPInfo.ParamByName('ParmCardCode').AsString := '%%'
    else
       qBPInfo.ParamByName('ParmCardCode').AsString := '%' + CardCode + '%';
    qBPInfo.Open;
    FDSchemaAdapterBPInfo.SaveToStream(Result, TFDStorageFormat.sfBinary);
    Result.Position := 0;
    //    Result.SaveToFile('output.adb');
    except
       raise;
  end;
end;

Here is my client code:

procedure TdmDataSnap.GetBPInfo(CardCode : String);
var
  LStringStream : TStringStream;
begin
  dmDataSnap.FDStoredProcBPInfo.ParamByName('CardCode').AsString := CardCode;
  FDStoredProcBPInfo.ExecProc;
  LStringStream := TStringStream.Create(FDStoredProcBPInfo.ParamByName('ReturnValue').asBlob);
  //LStringStream.Clear;
  //LStringStream.LoadFromFile('Output.adb');
  try
    if LStringStream <> nil then
    begin
      LStringStream.Position := 0;
      try
        DataModuleFDClient.FDSchemaAdapterBP.LoadFromStream(LStringStream, TFDStorageFormat.sfBinary);
      except
        on E : Exception do
        showmessage(e.Message);
      end;
    end;
  finally
    LStringStream.Free;
  end;
end;

You will see the stream save and load code; that is how I determined that the server was getting the entire result set into the stream, and that the client could handle the entire result set and display it properly.

So smaller streams transfer just fine, but this big one, when examined in the ide debugger, does not start with the 65,66,68,83 characters and the load fails with the error, '[FireDAC][Stan]-710. Invalid binary storage format'.

I know from extended Googling that there are work-arounds for this, but I do not understand how to apply the workarounds to my case, with the use of Tfdstoredproc and TfdSchemaAdaptor components. I'm trying to stay with this coding scheme.

How do I adapt this code to correctly receive large streams?

Update 1:

Ok, I tried strings and Base64 encoding. It didn't work.

Client Code:

procedure TdmDataSnap.GetBPInfo(CardCode : String);
var
  LStringStream : TStringStream;
  TempStream  : TStringStream;
begin
  dmDataSnap.FDStoredProcBPInfo.ParamByName('CardCode').AsString := CardCode;
  FDStoredProcBPInfo.ExecProc;
  try
    TempStream := TStringStream.Create;
    TIdDecoderMIME.DecodeStream(FDStoredProcBPInfo.ParamByName('ReturnValue').asString,TempStream);
    if TempStream <> nil then
    begin
      TempStream.Position := 0;
      try
        DataModuleFDClient.FDSchemaAdapterBP.LoadFromStream(TempStream, TFDStorageFormat.sfBinary);
      except
        on E : Exception do
        showmessage(e.Message);
      end;
    end;
  finally
    TempStream.Free;
  end;
end;

Here is my server code:

//Returns Customer Info
function TServerMethods.GetBPInfo(CardCode : String): String;
var
  TempStream  : TMemoryStream;
  OutputStr   : String;
begin
  Result := '';
  TempStream := TMemoryStream.Create;
  try
    try
      qBPInfo.Close;
      if CardCode.Trim = '' then
        qBPInfo.ParamByName('ParmCardCode').AsString := '%%'
      else
        qBPInfo.ParamByName('ParmCardCode').AsString := '%' + CardCode + '%';
      qBPInfo.Open;
      FDSchemaAdapterBPInfo.SaveToStream(TempStream, TFDStorageFormat.sfBinary);
      TempStream.Position := 0;
      OutputStr := IdEncoderMIMEBPInfo.EncodeStream(TempStream);
      Result := OutputStr
    except
      raise;
    end;
  finally
    TempStream.Free;
  end;
end;

The result is the same.

Mark Skeels
  • 85
  • 2
  • 7
  • 1
    This sounds like a similar problem to this one:http://stackoverflow.com/questions/41854631/cant-retrieve-tstreams-bigger-than-around-260-000-bytes-from-a-datasnap-server/41878153#41878153. As you'll see from my answer there, I couldn't get anywhere trying to solve this using a stream. but I had some success sending a string much larger than the longest stream I could send. Have you tried Base-64 coding like I suggested there? – MartynA Feb 16 '17 at 17:01
  • Not quite sure why whoever thought fit to downvote this - the problem is a show-stopper and easily reproducible, but i suspect its cause lurks in the transport layer underneath DataSnap, fwiw. – MartynA Feb 16 '17 at 19:20
  • 1,606,408 bytes (around 1.5 MB)? – mjn Feb 17 '17 at 06:55
  • Try to remove all the FireDAC stuff and transfer only stream loaded from file (not from BLOB). If that fails, you can exclude FireDAC and start blaming DataSnap ;) – Victoria Jun 16 '17 at 08:07

0 Answers0