uFileOperaObject.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. unit uFileOperaObject;
  2. interface
  3. uses
  4. SysUtils, SimpleMsgPack, Classes, Math, uCRCTools,
  5. uStreamCoderSocket, DTcpClient, uICoderSocket, uDTcpClientCoderImpl;
  6. type
  7. TFileOperaObject = class(TObject)
  8. private
  9. FFileSize:Int64;
  10. FFileCheckSum:Cardinal;
  11. FCoderSocket:ICoderSocket;
  12. FTcpClient: TDTcpClient;
  13. FCMDStream: TMemoryStream;
  14. FCMDObj:TSimpleMsgPack;
  15. function ChecksumAFile(pvFile:string): Cardinal;
  16. procedure pressINfo(pvSendObject: TSimpleMsgPack; pvRFile, pvType: String);
  17. public
  18. constructor Create;
  19. destructor Destroy; override;
  20. procedure checkConnect;
  21. procedure setHost(pvHost: string);
  22. procedure setPort(pvPort:Integer);
  23. procedure open;
  24. procedure close;
  25. procedure readFileINfo(pvRFile, pvType: string; pvChecksum: Boolean = true);
  26. function uploadFile(pvRFile:String; pvLocalFile:string; pvType:string): Int64;
  27. procedure downFile(pvRFile:String; pvLocalFile:string; pvType:string);
  28. procedure copyAFile(pvRFile, pvRDestFile, pvType: String);
  29. procedure deleteFile(pvRFile:String; pvType: string);
  30. class function verifyData(const buf; len:Cardinal): Cardinal;
  31. class function verifyStream(pvStream:TStream; len:Cardinal): Cardinal;
  32. property FileCheckSum: Cardinal read FFileCheckSum;
  33. property FileSize: Int64 read FFileSize;
  34. end;
  35. implementation
  36. const
  37. SEC_SIZE = 1024 * 50;
  38. procedure TFileOperaObject.checkConnect;
  39. begin
  40. try
  41. if not FTcpClient.Active then FTcpClient.Connect;
  42. except
  43. on E:Exception do
  44. begin
  45. raise Exception.CreateFmt('连接服务器出错[%s:%d]' + sLineBreak + E.Message,
  46. [FTcpClient.Host, FTcpClient.Port]);
  47. end;
  48. end;
  49. end;
  50. procedure TFileOperaObject.close;
  51. begin
  52. FTcpClient.Disconnect;
  53. end;
  54. procedure TFileOperaObject.copyAFile(pvRFile, pvRDestFile, pvType: String);
  55. var
  56. lvFileStream:TFileStream;
  57. lvRecvObj, lvSendObj:TSimpleMsgPack;
  58. i, l, lvSize:Integer;
  59. begin
  60. checkConnect;
  61. lvSendObj := TSimpleMsgPack.Create;
  62. lvRecvObj := TSimpleMsgPack.Create;
  63. try
  64. lvSendObj.Clear();
  65. lvSendObj.S['cmd.namespace'] := 'fileaccess';
  66. lvSendObj.I['cmd.index'] := 5; //copy文件
  67. lvSendObj.S['fileName'] := pvRFile;
  68. lvSendObj.S['newFile'] := pvRDestFile;
  69. lvSendObj.S['catalog'] := pvType;
  70. TStreamCoderSocket.SendObject(FCoderSocket, lvSendObj);
  71. TStreamCoderSocket.RecvObject(FCoderSocket, lvRecvObj);
  72. if not lvRecvObj.B['__result.result'] then
  73. begin
  74. raise Exception.Create(lvRecvObj.S['__result.msg']);
  75. end;
  76. finally
  77. lvSendObj.Free;
  78. lvRecvObj.Free;
  79. end;
  80. end;
  81. constructor TFileOperaObject.Create;
  82. begin
  83. inherited Create;
  84. FTcpClient := TDTcpClient.Create(nil);
  85. FCoderSocket := TDTcpClientCoderImpl.Create(FTcpClient);
  86. FCMDStream := TMemoryStream.Create;
  87. FCMDObj := TSimpleMsgPack.Create;
  88. end;
  89. procedure TFileOperaObject.deleteFile(pvRFile, pvType: string);
  90. var
  91. i, l, lvSize:Integer;
  92. begin
  93. checkConnect;
  94. FCMDObj.Clear();
  95. FCMDObj.S['cmd.namespace'] := 'fileaccess';
  96. FCMDObj.I['cmd.index'] := 4; //删除文件
  97. FCMDObj.S['fileName'] := pvRFile;
  98. FCMDObj.S['catalog'] := pvType;
  99. FCMDStream.Clear;
  100. FCMDObj.EncodeToStream(FCMDStream);
  101. TStreamCoderSocket.SendObject(FCoderSocket, FCMDStream);
  102. FCMDStream.Clear;
  103. TStreamCoderSocket.RecvObject(FCoderSocket, FCMDStream);
  104. FCMDStream.Position := 0;
  105. FCMDObj.DecodeFromStream(FCMDStream);
  106. if not FCMDObj.B['__result.result'] then
  107. begin
  108. raise Exception.Create(FCMDObj.S['__result.msg']);
  109. end;
  110. end;
  111. destructor TFileOperaObject.Destroy;
  112. begin
  113. FCMDStream.Free;
  114. FCMDObj.Free;
  115. FCoderSocket := nil;
  116. FTcpClient.Free;
  117. inherited Destroy;
  118. end;
  119. procedure TFileOperaObject.downFile(pvRFile, pvLocalFile, pvType: string);
  120. var
  121. lvRFileSize:Integer;
  122. var
  123. lvFileStream:TFileStream;
  124. i, l, lvSize:Integer;
  125. lvFileName:String;
  126. lvCrc, lvChecksum, lvLocalCheckSum:Cardinal;
  127. lvBytes:TBytes;
  128. begin
  129. checkConnect;
  130. //if FProgConsole <> nil then FProgConsole.SetHintText('正在获取远程文件大小');
  131. readFileINfo(pvRFile, pvType);
  132. lvRFileSize := FFileSize;
  133. if lvRFileSize = 0 then
  134. begin
  135. raise Exception.CreateFmt('远程文件[%s]不存在!', [pvRFile]);
  136. end;
  137. // if FProgConsole <> nil then
  138. // begin
  139. // FProgConsole.SetMax(lvRFileSize);
  140. // FProgConsole.SetPosition(0);
  141. // end;
  142. // lvCheckSum := FFileCheckSum;
  143. // if lvCheckSum = 0 then raise Exception.Create('服务端文件不存在!');
  144. lvLocalCheckSum := ChecksumAFile(pvLocalFile);
  145. if lvCheckSum = lvLocalCheckSum then
  146. begin
  147. // if FProgConsole <> nil then
  148. // begin
  149. // FProgConsole.SetHintText('秒传文件...');
  150. // FProgConsole.SetPosition(lvRFileSize);
  151. // Sleep(1000);
  152. // end;
  153. Exit;
  154. end;
  155. //将文件分段下载<每段固定大小>
  156. //循环发送
  157. // {
  158. // fileName:'xxxx', //客户端请求文件
  159. // start:0, //客户端请求开始位置
  160. // filesize:11111, //文件总大小
  161. // crc:xxxx, //服务端返回
  162. // blockSize:4096 //服务端返回
  163. // }
  164. lvFileName := pvLocalFile;
  165. SysUtils.DeleteFile(lvFileName);
  166. lvFileStream := TFileStream.Create(lvFileName, fmCreate or fmShareDenyWrite);
  167. try
  168. // if FProgConsole <> nil then
  169. // begin
  170. // FProgConsole.SetHintText('下载文件中...');
  171. // end;
  172. while true do
  173. begin
  174. // if FProgConsole <> nil then
  175. // begin
  176. // if FProgConsole.IsBreaked then Break;
  177. // end;
  178. FCMDObj.Clear();
  179. pressINfo(FCMDObj, pvRFile, pvType);
  180. FCMDObj.I['cmd.index'] := 1;
  181. FCMDObj.I['start'] := lvFileStream.Position;
  182. FCMDStream.Clear;
  183. FCMDObj.EncodeToStream(FCMDStream);
  184. TStreamCoderSocket.SendObject(FCoderSocket, FCMDStream);
  185. FCMDStream.Clear;
  186. TStreamCoderSocket.RecvObject(FCoderSocket, FCMDStream);
  187. FCMDStream.Position := 0;
  188. FCMDObj.DecodeFromStream(FCMDStream);
  189. if not FCMDObj.B['__result.result'] then
  190. begin
  191. raise Exception.Create(FCMDObj.S['__result.msg']);
  192. end;
  193. // lvCrc := TCRCTools.crc32Stream(lvRecvObj.Stream);
  194. // if lvCrc <> lvRecvObj.I['crc'] then
  195. // begin
  196. // raise Exception.Create('crc校验失败!');
  197. // end;
  198. lvBytes := FCMDObj.ForcePathObject('data').AsBytes;
  199. lvFileStream.Write(lvBytes[0], Length(lvBytes));
  200. // if FProgConsole <> nil then
  201. // begin
  202. // FProgConsole.SetPosition(lvFileStream.Position);
  203. // end;
  204. //文件下载完成
  205. if lvFileStream.Size = FCMDObj.I['fileSize'] then
  206. begin
  207. Break;
  208. end;
  209. end;
  210. finally
  211. lvFileStream.Free;
  212. end;
  213. end;
  214. function TFileOperaObject.ChecksumAFile(pvFile:string): Cardinal;
  215. var
  216. lvFileStream:TFileStream;
  217. lvCrc:Cardinal;
  218. begin
  219. result := 0;
  220. if FileExists(pvFile) then
  221. begin
  222. lvFileStream := TFileStream.Create(pvFile, fmOpenRead);
  223. try
  224. result := verifyStream(lvFileStream, 0);
  225. finally
  226. lvFileStream.Free;
  227. end;
  228. end;
  229. end;
  230. procedure TFileOperaObject.open;
  231. begin
  232. FTcpClient.Connect;
  233. end;
  234. procedure TFileOperaObject.pressINfo(pvSendObject: TSimpleMsgPack; pvRFile,
  235. pvType: String);
  236. begin
  237. pvSendObject.S['cmd.namespace'] := 'fileaccess';
  238. pvSendObject.S['fileName'] := pvRFile;
  239. pvSendObject.S['catalog'] := pvType;
  240. end;
  241. procedure TFileOperaObject.readFileINfo(pvRFile, pvType: string; pvChecksum:
  242. Boolean = true);
  243. var
  244. lvFileStream:TFileStream;
  245. i, l, lvSize:Integer;
  246. begin
  247. checkConnect;
  248. FCMDObj.Clear();
  249. FCMDObj.S['cmd.namespace'] := 'fileaccess';
  250. FCMDObj.I['cmd.index'] := 3; //文件信息
  251. FCMDObj.B['cmd.checksum'] := pvChecksum; //获取checksum值
  252. FCMDObj.S['fileName'] := pvRFile;
  253. FCMDObj.S['catalog'] := pvType;
  254. FCMDStream.Clear;
  255. FCMDObj.EncodeToStream(FCMDStream);
  256. TStreamCoderSocket.SendObject(FCoderSocket, FCMDStream);
  257. FCMDStream.Clear;
  258. TStreamCoderSocket.RecvObject(FCoderSocket, FCMDStream);
  259. FCMDStream.Position := 0;
  260. FCMDObj.DecodeFromStream(FCMDStream);
  261. if not FCMDObj.B['__result.result'] then
  262. begin
  263. raise Exception.Create(FCMDObj.S['__result.msg']);
  264. end;
  265. FFileSize := FCMDObj.I['info.size'];
  266. FFileCheckSum := FCMDObj.I['info.checksum'];
  267. end;
  268. procedure TFileOperaObject.setHost(pvHost: string);
  269. begin
  270. FTcpClient.Host := pvHost;
  271. end;
  272. procedure TFileOperaObject.setPort(pvPort: Integer);
  273. begin
  274. FTcpClient.Port := pvPort;
  275. end;
  276. { TFileOperaObject }
  277. function TFileOperaObject.uploadFile(pvRFile:String; pvLocalFile:string;
  278. pvType:string): Int64;
  279. var
  280. lvFileStream:TFileStream;
  281. lvPosition, i, l, lvSize:Int64;
  282. lvCheckSum, lvLocalCheckSum:Cardinal;
  283. begin
  284. //将文件分段传递<每段固定大小> 4K
  285. //循环发送
  286. // {
  287. // fileName:'xxxx',
  288. // crc:xxxx,
  289. // start:0, //开始位置
  290. // eof:true, //最后一个
  291. // }
  292. checkConnect;
  293. //lvLocalCheckSum := ChecksumAFile(pvLocalFile);
  294. lvFileStream := TFileStream.Create(pvLocalFile, fmOpenRead);
  295. try
  296. //readFileINfo(pvRFile, pvType);
  297. // lvCheckSum := FFileCheckSum;
  298. //
  299. //
  300. // if lvCheckSum = lvLocalCheckSum then
  301. // begin
  302. //// if FProgConsole <> nil then
  303. //// begin
  304. //// FProgConsole.SetHintText('秒传文件...');
  305. //// FProgConsole.SetPosition(lvFileStream.Size);
  306. //// Sleep(1000);
  307. //// end;
  308. // Exit;
  309. // end;
  310. while true do
  311. begin
  312. // if FProgConsole <> nil then
  313. // begin
  314. // if FProgConsole.IsBreaked then Break;
  315. // end;
  316. //
  317. FCMDObj.Clear();
  318. if pvRFile = '' then
  319. begin
  320. pressINfo(FCMDObj, ExtractFileName(pvLocalFile), pvType);
  321. end else
  322. begin
  323. pressINfo(FCMDObj, pvRFile, pvType);
  324. end;
  325. FCMDObj.S['cmd.namespace'] := 'fileaccess';
  326. FCMDObj.I['cmd.index'] := 2; //上传文件
  327. lvPosition:=lvFileStream.Position;
  328. FCMDObj.I['start'] := lvPosition;
  329. // if lvFileStream.Position = 102400 then
  330. // begin
  331. // FCMDObj.I['start'] := lvFileStream.Position;
  332. // end;
  333. // if lvFileStream.Position = 0 then
  334. // begin
  335. // FCMDObj.I['start'] := 0;
  336. // end;
  337. // FCMDObj.S['startStr'] := IntToStr(lvFileStream.Position);
  338. lvSize := Min(SEC_SIZE, lvFileStream.Size-lvFileStream.Position);
  339. if lvSize = 0 then
  340. begin
  341. Break;
  342. end else
  343. begin
  344. FCMDObj.ForcePathObject('data').LoadBinaryFromStream(lvFileStream, lvSize);
  345. FCMDObj.I['size'] := lvSize;
  346. if (lvFileStream.Position = lvFileStream.Size) then
  347. begin
  348. FCMDObj.B['eof'] := true;
  349. end;
  350. FCMDStream.Clear;
  351. FCMDObj.EncodeToStream(FCMDStream);
  352. TStreamCoderSocket.SendObject(FCoderSocket, FCMDStream);
  353. FCMDStream.Clear;
  354. TStreamCoderSocket.RecvObject(FCoderSocket, FCMDStream);
  355. FCMDStream.Position := 0;
  356. FCMDObj.DecodeFromStream(FCMDStream);
  357. if not FCMDObj.B['__result.result'] then
  358. begin
  359. raise Exception.Create(FCMDObj.S['__result.msg']);
  360. end;
  361. // if FProgConsole <> nil then
  362. // begin
  363. // FProgConsole.SetPosition(lvFileStream.Position);
  364. // end;
  365. if (lvFileStream.Position = lvFileStream.Size) then
  366. begin
  367. Break;
  368. end;
  369. end;
  370. end;
  371. Result := lvFileStream.Size;
  372. finally
  373. lvFileStream.Free;
  374. end;
  375. end;
  376. class function TFileOperaObject.verifyData(const buf; len: Cardinal): Cardinal;
  377. var
  378. i:Cardinal;
  379. p:PByte;
  380. begin
  381. i := 0;
  382. Result := 0;
  383. p := PByte(@buf);
  384. while i < len do
  385. begin
  386. Result := Result + p^;
  387. Inc(p);
  388. Inc(i);
  389. end;
  390. end;
  391. class function TFileOperaObject.verifyStream(pvStream:TStream; len:Cardinal):
  392. Cardinal;
  393. var
  394. l, j:Cardinal;
  395. lvBytes:TBytes;
  396. begin
  397. SetLength(lvBytes, 1024);
  398. if len = 0 then
  399. begin
  400. j := pvStream.Size - pvStream.Position;
  401. end else
  402. begin
  403. j := len;
  404. end;
  405. Result := 0;
  406. while j > 0 do
  407. begin
  408. if j <1024 then l := j else l := 1024;
  409. pvStream.ReadBuffer(lvBytes[0], l);
  410. Result := Result + verifyData(lvBytes[0], l);
  411. Dec(j, l);
  412. end;
  413. end;
  414. end.