DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: xiao2024
今日帖子: 18
在线用户: 13
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/12 23:28:22
标题:
datasnap服务器返回stream出错 浏览:1585
加入我的收藏
楼主: 请教大家一个问题
 
环境:WIN7 + Delphi 10.1 berlin
  
我在服务器上定义一个函数 

function TServerMethods.GetStream(const aSQL: string): TStream;
var
 
  qry : TFDquery ;
begin
  begin
    try
      if Trim(aSQL) = EmptyStr then
        exit;

 
      qry := Tfdquery.Create(nil)
      with qry do
      begin
        Connection := conLocal; //一个成功的连接FDConnection
        close;
        sql.Text := aSQL;
        open;
      end; 
      Result := TMemoryStream.Create;
      qry.SaveToStream(Result);
      Result.Position := 0;
    except
      on e: Exception do
      begin
        log.Error(e.Message, self.ClassName + '.OpenSQL');
      end;
    end;
  end;

end;

奇怪的现象是:
如果客户端调用返回的数据集行数比较少没有问题,一旦多一点(如200条),客户端出错,提示  [Firedac][stan]cannot  read [manager] object 

请帮忙分析下,是什么原因引起的?
----------------------------------------------
-把学习当信仰
作者:
男 wang_80919 (Flying Wang) ★☆☆☆☆ -
普通会员
2018/10/12 23:45:33
1楼: c and s
uses MidasLib;
----------------------------------------------
(C)(P)Flying Wang
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/12 23:57:54
2楼: 什么意思
----------------------------------------------
-把学习当信仰
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 0:01:03
3楼: 加了,没用
----------------------------------------------
-把学习当信仰
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 0:30:32
4楼: datasnap stream返回有大小限制?
----------------------------------------------
-把学习当信仰
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 8:32:22
5楼: 大家不用tstream来交换数据吗
----------------------------------------------
-把学习当信仰
作者:
男 lsh341999 (虫子) ★☆☆☆☆ -
普通会员
2018/10/13 9:29:35
6楼: 在客户端读取流应该是
  Function GetSendStream(ASendStream:TStream):TMemoryStream;
  Var
    buf: array[0..131071]  of byte;
    Index:Integer;
  Begin
    Result:=TMemoryStream.Create;
    repeat
      Index:=ASendStream.Read(buf, sizeof(buf));
      if Index > 0 then
        Result.Write(Buf,Index);
    until Index=0;
    Result.Position:=0;
  End;
----------------------------------------------
就怕想不到,没有做不到的
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 13:46:14
7楼: 楼上,我在客户端是用fdmemtable.loadfromstream来获取服务器端函数的返回值,这样有问题吗? 你上面函数中指定为131071,有特别涵义吗 ?
----------------------------------------------
-把学习当信仰
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 14:35:05
8楼: 这样是可以了,好奇为什么TFDmemtable的loadfromstream不行,另外,这个131071如果换成最大值,应该是多少
----------------------------------------------
-把学习当信仰
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 15:23:59
9楼: https://www.cnblogs.com/hnxxcxg/archive/2012/11/23/2785088.html

根据上面的地址改装,出现rang check error,不知什么原因
----------------------------------------------
-把学习当信仰
作者:
男 lsh341999 (虫子) ★☆☆☆☆ -
普通会员
2018/10/13 17:27:04
10楼:  时间太久了,我也不记得这131071有啥物别函义
反正就这样
----------------------------------------------
就怕想不到,没有做不到的
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/13 19:33:23
11楼: 如果返回几百万条记录可能就会出错
----------------------------------------------
-把学习当信仰
作者:
男 lsh341999 (虫子) ★☆☆☆☆ -
普通会员
2018/10/15 9:50:18
12楼: 新测这种方式
可以传送3G多的文件都不会出错
当然TMemoryStream要换成文件流
----------------------------------------------
就怕想不到,没有做不到的
作者:
男 wang_80919 (Flying Wang) ★☆☆☆☆ -
普通会员
2018/10/15 11:23:12
13楼: 但是一次申请那么大的内存没必要,反正是循环的。 9 楼代码和你的就是  buf 大小不一样。其他都一样。
建议用 9 楼的 buf 大小。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2018/10/15 12:46:32
14楼: 用stream有些问题,但用Json就没有这种问题,我用json向数据库传图片和从数据库取出图片显示在手机上,照片几个M,暂时没有发现传输的问题。
 另外, buf: array[0..131071]  of byte;这种在win32/64上正常,但在ios/android上不一定正常。
----------------------------------------------
-
作者:
男 bmsr (白忙剩人) ★☆☆☆☆ -
普通会员
2018/10/15 14:28:52
15楼: procedure TForm_Main.Button4Click(Sender: TObject);
const
  BufSize = $F000;
var
  buf: Tbytes;
  fs: TFileStream;
  st: TStream;
  FName, SaveFileName: string;
  conn: TSQLConnection;
  DBXCommand: TDBXCommand;
  errcode: integer;
  //  asize: int64;
  readcount: integer;
  s: string;
begin
  if SaveDialog1.Execute then
    begin

      //      FName := Edit1.Text;
      SaveFileName := ExtractFilePath(SaveDialog1.FileName) + ExtractFileName(FName);
      conn := DM.GetSQLConn;
      try
        if not conn.Connected then conn.Open;
        fs := TFileStream.Create(SaveFileName, fmCreate, fmShareDenyWrite);
        DBXCommand := conn.DBXConnection.CreateCommand;
        try
          DBXCommand.CommandType := TDBXCommandTypes.DSServerMethod;
          DBXCommand.Text := 'TSrvMethods.DownFileMsg';
          DBXCommand.Prepare;
          DBXCommand.Parameters[0].Value.SetWideString(FName);
          //          Memo1.Lines.Add('开始下载文件!');
          DBXCommand.ExecuteUpdate;
          errcode := DBXCommand.Parameters[1].Value.AsInt32;
          if errcode <> 0 then
          begin
          //          Memo1.Lines.Add('下载失败!错误代码:' + inttostr(errcode));
          exit;
          end;
          //          asize := DBXCommand.Parameters[2].Value.AsInt64;

          st := DBXCommand.Parameters[3].Value.GetStream(False);
          if st.Size = -1 then
          begin
          SetLength(buf, BufSize);
          repeat
          readcount := st.Read(buf[0], BufSize);
          if readcount > 0 then fs.WriteBuffer(buf[0], readcount);
          until readcount < BufSize;
          end
          else
          begin
          fs.CopyFrom(st, 0);
          end;
          s := DBXCommand.Parameters[4].Value.GetString;
          Memo_info.Lines.Add(Format('文件下载完成!' + #13#10 + '大小:%d', [fs.Size]));
          Memo_info.Lines.Add(s);
        finally
          DBXCommand.Free;
          fs.Free;
          st.Free;
        end;

      finally
        DM.ReleaseSQLConn(conn);
      end;
    end; // SaveDialog1

end;


function TSrvMethods.DownFileMsg(aFilePath: String; out Errcode: integer; out aSize: Int64; out outStream: TStream): string;
begin
  result := FalseStr;
  try
    if Assigned(outStream) then outStream.Free;
    Errcode := 0;
    aSize := 0;
    if not FileExists(aFilePath) then
      begin
        Errcode := -1;
        exit; //文件不存在
      end;
    outStream := TFileStream.Create(aFilePath, fmOpenRead, fmShareDenyWrite);
    try
      //     result := fs;
      aSize := outStream.Size;
      outStream.Position := 0;
      result := TrueStr;
    finally
      //    fs.Free;
    end;
  except
    on E: Exception do result := E.Message;
  end;
end;

当传输的数据较大时,必须分段传输读取,一次最大传输是多少忘了好像是200K,但这没关系,随便取合适的暂存空间即可,此列子传送超过4G的特大文件也没有问题的。
----------------------------------------------
http://blog.sina.com.cn/bmsrnote
作者:
男 wanlgrm (么么) ▲▲▲▲▲ -
普通会员
2018/10/15 15:11:36
16楼: DataSnap的书需要仔细看啊,官方出的流的处理方式
      LStream := GetServerMethodsUnitClient.QueryDataSet(ASql, AError);
      if AError = EmptyStr then
      begin
        if LStream <> nil then
          AStream := CopyStream(LStream);
        AStream.Position := 0;
        LoadFromStream(AStream, TFDStorageFormat.sfBinary);


function CopyStream(const AStream: TStream): TMemoryStream;
const
  LBufSize = $F000;
var
  LBuffer: TBytes;
  LReadLen: Integer;
begin
  Result := nil;
  if AStream = nil then
    Exit;
  Result := TMemoryStream.Create;
  try
    if AStream.Size = -1 then
    begin
      SetLength(LBuffer, LBufSize);
      repeat
        LReadLen := AStream.Read(LBuffer[0], LBufSize);
        if LReadLen > 0 then
          Result.WriteBuffer(LBuffer[0], LReadLen);
        if LReadLen < LBufSize then
          break;
      until LReadLen < LBufSize;
    end
    else
      Result.CopyFrom(AStream, 0);
    Result.Position := 0;
  except
    Result.Free;
  end;
end;
----------------------------------------------
-只会复制粘贴!
作者:
男 wanlgrm (么么) ▲▲▲▲▲ -
普通会员
2018/10/15 15:12:54
17楼: https://www.cnblogs.com/hnxxcxg/p/7770471.html

http://www.cnblogs.com/Thenext/p/9780382.html  

你看这些大佬的帖子写的很清楚
----------------------------------------------
-只会复制粘贴!
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2018/10/17 17:54:15
18楼: 感谢各位,可以了!
----------------------------------------------
-把学习当信仰
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行85.9375毫秒 RSS