DataSnap可以直接傳遞和返回TStream類型的參數,這點是很方便的。但是很多人發現好像大小稍微大點就工作不正常了。
DataSnap預設的緩衝大小是32k 所以如果流的大小超過這個大小就會被自動分成多個包,這就是傳遞大量資料的基礎,如果一次性發送就可能受到記憶體的限制。
當傳遞大量資料時擷取到的大小是-1,所以如果還是按照一般的方法來讀取流的資料就會有問題了。
由於流的資料是未經處理資料包發送,所以在不對資料包壓縮加密的情況下,傳遞速度是和其它方式沒有多大區別的。
0102030405060708091011121314151617181920212223 |
// FS是一個檔案流 function TMyDSServer . PutFile(Stream: TStream): Boolean ; const BufSize = $F000 ; var Buffer: TBytes; ReadCount: Integer ; begin if Stream . Size = - 1 then // 大小未知則一直讀取到沒有資料為止 begin SetLength(Buffer, BufSize); repeat ReadCount := Stream . Read(Buffer[ 0 ], BufSize); if ReadCount > 0 then FS . WriteBuffer(Buffer[ 0 ], ReadCount); if ReadCount < BufSize then break; until ReadCount < BufSize; end else // 大小已知則直接複製資料 FS . CopyFrom(Stream, 0 ); Result := True ; end ; |
function TdmCommonFun.DownLoadFile(const FileName: string): Boolean;
var
a: TServerMethods1Client;
ini: TIniFile;
Stream, ms: TStream;
Buffer: TBytes;
ReadCount: Integer;
const
BufSize = $F000;
begin
Result := False;
if (not TryConnectAPPServer) or (FileName = '') then
Exit;
a := TServerMethods1Client.Create(SQLConnection1.DBXConnection);
ms := TMemoryStream.Create;
try
Stream := a.DownLoadFile(FileName);
if Stream.Size = -1 then
begin
SetLength(Buffer, BufSize);
repeat
ReadCount := Stream.Read(Buffer[0], BufSize);
if ReadCount > 0 then
ms.WriteBuffer(Buffer[0], ReadCount);
if ReadCount < BufSize then
break;
until ReadCount < BufSize;
end
else
begin
ms.CopyFrom(Stream, 0);
end;
// delete bak files
if FileExists(ExtractFilePath(Application.ExeName) + FileName + 'bak') then
DeleteFile(PWideChar(ExtractFilePath(Application.ExeName) + FileName
+ 'bak'));
// 現有檔案改名
if FileExists(ExtractFilePath(Application.ExeName) + FileName) then
begin
RenameFile(ExtractFilePath(Application.ExeName) + FileName,
ExtractFilePath(Application.ExeName) + FileName + 'bak');
end;
// 下載最新檔案
TMemoryStream(ms).SaveToFile(ExtractFilePath(Application.ExeName) +
FileName);
// 更新本機版本號碼
ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'client.ini');
try
ini.WriteInteger(FileName, 'ver', GetVer(FileName));
finally
ini.Free;
end;
finally
a.Free;
ms.Free;
end;
Result := True;
end;