简体   繁体   中英

passing a TStream using Data Snap in Delphi XE6

I am in need of passing a couple things using Data Snap in Delphi XE6 ( TStream & TClientdataSet ). Lets start with a TStream - maybe what I learn here, I can figure out the TClientDataSet .

Here is my attempt, but it throws an error:

Remote error: Access violaion at address 0040801C in module DSServer.exe

Client demo (DSClient.exe)

//RunReportObj is the real object I will be passing to the server method

Procedure TForm8.Button1Click(Sender: TObject);
var
  RunReportObj: TRunReportObject;
  S: TStream;
  FS: TFileStream;
begin
  RunReportObj:= TRunReportObject.Create;
  RunReportObj.ID:= '10101';
  RunReportObj.ReportName:= 'Test';
  RunReportObj.ExportType:= 'PDF';
  S:= TStream.Create;
   try
    S:= ClientModule1.ServerMethods1Client.GetReport(RunReportObj);
    S.Seek(0,soFromBeginning);
    FS:= TFileStream.Create(RunReportObj.ReportName + '.' + RunReportObj.ExportType, fmOpenWrite);;
    try
      FS.CopyFrom(S, S.Size);
    finally
      FS.Free;
    end;
   finally
    S.Free;
   end;
end;

ClientClassesUnit1.pas

function TServerMethods1Client.GetReport(RunReportObj: TRunReportObject): TStream;
begin
  if FGetReportCommand = nil then
  begin
    FGetReportCommand := FDBXConnection.CreateCommand;
    FGetReportCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FGetReportCommand.Text := 'TServerMethods1.GetReport';
    FGetReportCommand.Prepare;
  end;
  if not Assigned(RunReportObj) then
    FGetReportCommand.Parameters[0].Value.SetNull
  else
  begin
    FMarshal := TDBXClientCommand(FGetReportCommand.Parameters[0].ConnectionHandler).GetJSONMarshaler;
    try
      FGetReportCommand.Parameters[0].Value.SetJSONValue(FMarshal.Marshal(RunReportObj), True);
      if FInstanceOwner then
        RunReportObj.Free
    finally
      FreeAndNil(FMarshal)
    end
    end;
  FGetReportCommand.ExecuteUpdate;
  Result := FGetReportCommand.Parameters[1].Value.GetStream(FInstanceOwner);
end;

Server demo (DSServer.exe)

//not really doing anything with the RunReportObj yet,
// just trying to test whether or not I can pass a TStream back first

function TServerMethods1.GetReport(RunReportObj: TRunReportObject): TStream;
var
  Stream: TMemoryStream;
  Writer: TBinaryWriter;
  Bytes: TBytes;
begin
  result := TMemoryStream.Create;
  try
    Writer := TBinaryWriter.Create(result);
    try
      Writer.Write(TEncoding.UTF8.GetBytes('Hello World' + sLineBreak));
    finally
      Writer.Free;
    end;
  finally
    Stream.Free;
  end;
end;

I'm sure I did something foolish :)

You have to take care who is responsible for freeing objects sent with DataSnap. TServerMethods1.GetReport() should not free the Result , as it has to be sent to the client first. On the other side, the client should not free the TStream it gets from TServerMethods1Client.GetReport() , as long as FInstanceOwner is true (which it is by default).

The first condition is fulfilled more by accident, although as David pointed out, you are freeing the uninitialized local variable Stream.

Without being able to actually test this in the moment, the correct code for the client should look like:

Procedure TForm8.Button1Click(Sender: TObject);
var
  RunReportObj: TRunReportObject;
  S: TStream;
  FS: TFileStream;
begin
  RunReportObj:= TRunReportObject.Create;
  RunReportObj.ID:= '10101';
  RunReportObj.ReportName:= 'Test';
  RunReportObj.ExportType:= 'PDF';
  S:= ClientModule1.ServerMethods1Client.GetReport(RunReportObj);
  S.Seek(0,soFromBeginning);
  FS:= TFileStream.Create(RunReportObj.ReportName + '.' + RunReportObj.ExportType, fmOpenWrite);;
  try
    FS.CopyFrom(S, S.Size);
  finally
    FS.Free;
  end;
end;

And for the server side:

function TServerMethods1.GetReport(RunReportObj: TRunReportObject): TStream;
var
  Writer: TBinaryWriter;
  Bytes: TBytes;
begin
  result := TMemoryStream.Create;
  Writer := TBinaryWriter.Create(result);
  try
    Writer.Write(TEncoding.UTF8.GetBytes('Hello World' + sLineBreak));
  finally
    Writer.Free;
  end;
end;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM