【问题标题】:How to pass and return a Stream using DataSnap in Delphi XE6?如何在 Delphi XE6 中使用 DataSnap 传递和返回 Stream?
【发布时间】:2016-06-08 13:43:57
【问题描述】:

如何在 Delphi XE6 中使用 DataSnap 传递和返回 Stream?

当我调用服务器端方法时,我的流是正确的类,具有大小和位置。然而,当它遇到我的客户时,这个类不是我所期望的,它没有大小或位置

//客户端代码

 procedure TForm1.brnGetReportClick(Sender: TObject);
    var
      RunReportObj: TRunReportObject;
      S: TStream;
      FS: TFileStream;
    begin
       ....
       try
          S:= (ClientModule1.ServerMethods1Client.getReport(RunReportObj));
          //ShowMessage('Class = ' + S.ClassName + #10#13 +
          //            'Size = ' + intToStr(S.Size) + #10#13 +
          //            'Position = ' + intToStr(S.Position));
          S.Position:= 0;
          FS:= TFileStream.Create('test.rpt', fmCreate or fmOpenWrite);
          FS.Position:= 0;
          try
            FS.CopyFrom(S, S.Size);
          finally
            FS.Free;
          end;
        finally
          S.Free
        end;
    end;

我在上面代码中的调试显示信息,显示如下

Class = TDBXStreamReaderStream
Size = -1
Position = 0

//服务器端方法

function getReport(const ARunReportObj: TRunReportObject): TStream;
var
  r: String;
  SS: TStringStream;
begin

   result:= TMemoryStream.Create;

   r := getRunReportJSON(ARunReportObj);
   SS := TStringStream.Create(r, TEncoding.ASCII);
   try
     try       
       ServerContainer1.idHttp1.Post
('https://imserver1.runit.com/isapi/isellitreporttest.dll/isellit', SS, result);
      ShowMessage('Class = ' + Result.ClassName + #10#13 +
                  'Size = ' + intToStr(result.Size) + #10#13 +
                  'Position = ' + intToStr(result.Position));
        Result.Position:= 0;
     except
     end;
   finally
    SS.Free;
   end;
end;

我在上面代码中的调试显示信息,显示如下

Class = TMemoryStream 
Size = 373760 
Position = 373760

【问题讨论】:

    标签: delphi datasnap


    【解决方案1】:

    这是设计的。 DataSnap 仅保证您从服务器获得TStream,而不保证它实际上是哪个类。您可以从中阅读,但仅此而已。

    Position = 0 也是预期的,因为这是您在服务器中设置的。另一方面,我不确定Position = 0 之类的其他东西是否有用,所以如果您在客户端收到Position = 0,我也不会感到惊讶。虽然,当服务器之前没有将其设置为 0 时,流可能不会在预期位置开始。

    对于Size 属性,我参考TStream 文档:

    Size 属性通常以字节为单位指示流的大小。但是 TStream 的后代可以使用 -1 来表示未知大小。当大小未知时,使用 TStream.Read 的返回值来确定流的结束。

    您应该知道,DataSnap 不一定会在调用getReport 时传输流内容,但当您从客户端调用Read 时可能会这样做。这允许像电影或广播播客这样的无尽流。

    【讨论】:

    • 感谢您的回复。所以,为了修复我的代码(如果可能的话?),我只需要使用 TStream.Read 来获取大小,还是分块读取?
    • 您的代码建议您要将整个流存储到文件中。你不需要尺寸来做到这一点。如果将 0 作为 CopyFrom 的第二个参数,它将复制整个流。这就是文档所说的:“如果 Count 为 0,CopyFrom 在读取之前将 Source 位置设置为 0,然后将 Source 的全部内容复制到流中。”
    【解决方案2】:

    服务器:

    客户端到服务器

    function Tform_methodos.SendStream(st:TStream): string;
    var sm : TMemoryStream;
    begin
        ...
        sm:=TMemoryStream.create;
        sm.LoadFromStream(st);
        sm.SaveToFile(pasta+'\test.bin');
        sm.free;
    end;
    

    服务器到客户端:

    function Tform_methodos.GetStream(var size : integer):Tstream;
    begin
        ...
        result:=TmemoryStream.create;
        TmemoryStream(result).LoadFromFile('test.bin');
        size:=TmemoryStream(result).Size;
    end;
    

    客户: 客户端到服务器

    var sm : TMemoryStream
        error : string;
    begin
        ...
        sm:=TMemoryStream.create;
        sm.LoadFromFile('test.bin');
        error:=server.SendStream(sm);
        sm.Free;
    end;
    

    服务器到客户端

    var sm : TmemoryStream;
        st : TStream;
        size : integer; 
    begin
        ...
        sm:=TMemorystream.create;
        st:=server.GetStream(size);
        sm.CopyFrom(st,size);
        sm.SaveToFile('test.bin');
        sm.free;
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-30
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-20
      • 1970-01-01
      相关资源
      最近更新 更多