Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在DelphiXe6中使用DataSnap传递和返回流?_Delphi_Datasnap - Fatal编程技术网

如何在DelphiXe6中使用DataSnap传递和返回流?

如何在DelphiXe6中使用DataSnap传递和返回流?,delphi,datasnap,Delphi,Datasnap,如何在DelphiXe6中使用DataSnap传递和返回流 当我调用服务器端方法时,我的流是正确的类,具有大小和位置。然而,当涉及到我的客户时,这个类不是我所期望的,它没有大小或位置 //客户端代码 procedure TForm1.brnGetReportClick(Sender: TObject); var RunReportObj: TRunReportObject; S: TStream; FS: TFileStream; begin

如何在DelphiXe6中使用DataSnap传递和返回流

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

//客户端代码

 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;
上面代码中的My debugging showmessage显示以下内容

Class = TDBXStreamReaderStream
Size = -1
Position = 0
Class = TMemoryStream 
Size = 373760 
Position = 373760
//服务器端方法

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;
上面代码中的My debugging showmessage显示以下内容

Class = TDBXStreamReaderStream
Size = -1
Position = 0
Class = TMemoryStream 
Size = 373760 
Position = 373760

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

Position=0
也是预期值,因为这是您在服务器中设置的值。另一方面,我不确定像
Position=0
这样的东西是否有用,所以如果你在客户端得到
Position=0
,我也不会感到惊讶。尽管如此,当服务器之前没有将my流设置为0时,my流不会在预期位置启动

有关
Size
属性,请参阅
TStream
文档:

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


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

服务器:

客户端到服务器

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;
var sm : TMemoryStream
    error : string;
begin
    ...
    sm:=TMemoryStream.create;
    sm.LoadFromFile('test.bin');
    error:=server.SendStream(sm);
    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;
客户端: 客户端到服务器

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

谢谢你的回复。因此,为了修复我的代码(如果可能的话?),我只需要使用TStream.Read来获取大小,或者分块读取?您的代码表明,您希望将整个流存储到一个文件中。你不需要那么大的尺寸。如果将0作为CopyFrom的第二个参数,它将复制整个流。这就是文档所说的:“如果Count为0,则CopyFrom在读取之前将Source位置设置为0,然后将Source的全部内容复制到流中。”