Quick.Azure.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. { ***************************************************************************
  2. Copyright (c) 2015-2020 Kike Pérez
  3. Unit : Quick.Azure
  4. Description : Azure blobs operations
  5. Author : Kike Pérez
  6. Version : 1.4
  7. Created : 27/08/2015
  8. Modified : 05/11/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Azure;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. System.SysUtils,
  27. System.Generics.Collections,
  28. IPPeerClient,
  29. IdURI,
  30. Data.Cloud.CloudAPI,
  31. Data.Cloud.AzureAPI,
  32. Quick.Commons;
  33. type
  34. TAzureProtocol = (azHTTP,azHTTPS);
  35. //TAzureBlob = Data.Cloud.AzureAPI.TAzureBlob;
  36. TBlobPublicAccess = Data.Cloud.AzureAPI.TBlobPublicAccess;
  37. TAzureResponseInfo = record
  38. StatusCode : Integer;
  39. StatusMsg : string;
  40. end;
  41. TAzureBlobObject = class
  42. Name : string;
  43. Size : Int64;
  44. IsDir : Boolean;
  45. LastModified : TDateTime;
  46. end;
  47. TBlobList = class (TObjectList<TAzureBlobObject>);
  48. TQuickAzure = class
  49. private
  50. fconAzure : TAzureConnectionInfo;
  51. fAccountName : string;
  52. fAccountKey : string;
  53. fAzureProtocol : TAzureProtocol;
  54. fTimeOut : Integer;
  55. procedure SetAccountName(azAccountName : string);
  56. procedure SetAccountKey(azAccountKey : string);
  57. procedure SetAzureProtocol(azProtocol : TAzureProtocol);
  58. function FileToArray(cFilename : string) : TArray<Byte>;
  59. function StreamToArray(cStream : TStream) : TArray<Byte>;
  60. function ByteContent(DataStream: TStream): TBytes;
  61. function GMT2DateTime(const gmtdate : string):TDateTime;
  62. function CheckContainer(const aContainer : string) : string;
  63. function RemoveFirstSlash(const aValue : string) : string;
  64. public
  65. constructor Create; overload;
  66. constructor Create(azAccountName, azAccountKey : string); overload;
  67. destructor Destroy; override;
  68. property AccountName : string read fAccountName write SetAccountName;
  69. property AccountKey : string read fAccountKey write SetAccountKey;
  70. property AzureProtocol : TAzureProtocol read fAzureProtocol write SetAzureProtocol;
  71. property TimeOut : Integer read fTimeOut write fTimeOut;
  72. function PutBlob(const azContainer, cFilename, azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean; overload;
  73. function PutBlob(const azContainer : string; cStream : TStream; const azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean; overload;
  74. function GetBlob(const azContainer, azBlobName, cFilenameTo : string; out azResponseInfo : TAzureResponseInfo) : Boolean; overload;
  75. function GetBlob(const azContainer, azBlobName : string; out azResponseInfo : TAzureResponseInfo; out Stream : TMemoryStream) : Boolean; overload;
  76. function GetBlob(const azContainer, azBlobName: string; out azResponseInfo: TAzureResponseInfo; var Stream: TStream): Boolean; overload;
  77. function GetBlob(const azContainer, azBlobName : string; out azResponseInfo : TAzureResponseInfo) : TMemoryStream; overload;
  78. function CopyBlob(const azSourceContainer, azSourceBlobName : string; azTargetContainer, azTargetBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  79. function RenameBlob(const azContainer, azSourceBlobName, azTargetBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  80. function ExistsObject(const azContainer, azBlobName : string) : Boolean;
  81. function ExistsFolder(const azContainer, azFolderName : string) : Boolean;
  82. function DeleteBlob(const azContainer,azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  83. function ListBlobs(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TBlobList;
  84. function ListBlobsNames(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TStrings;
  85. function ExistsContainer(const azContainer : string) : Boolean;
  86. function ListContainers(const azContainersStartWith : string; out azResponseInfo : TAzureResponseInfo) : TStrings;
  87. function CreateContainer(const azContainer : string; azPublicAccess : TBlobPublicAccess; out azResponseInfo : TAzureResponseInfo) : Boolean;
  88. function DeleteContainer(const azContainer : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  89. end;
  90. implementation
  91. constructor TQuickAzure.Create;
  92. begin
  93. inherited;
  94. fconAzure := TAzureConnectionInfo.Create(nil);
  95. fAzureProtocol := azHTTP;
  96. fTimeOut := 30;
  97. end;
  98. constructor TQuickAzure.Create(azAccountName, azAccountKey : string);
  99. begin
  100. Create;
  101. SetAccountName(azAccountName);
  102. SetAccountKey(azAccountKey);
  103. end;
  104. destructor TQuickAzure.Destroy;
  105. begin
  106. if Assigned(fconAzure) then fconAzure.Free;
  107. inherited;
  108. end;
  109. procedure TQuickAzure.SetAccountName(azAccountName : string);
  110. begin
  111. if fAccountName <> azAccountName then
  112. begin
  113. fAccountName := azAccountName;
  114. fconAzure.AccountName := azAccountName;
  115. end;
  116. end;
  117. procedure TQuickAzure.SetAccountKey(azAccountKey : string);
  118. begin
  119. if fAccountKey <> azAccountKey then
  120. begin
  121. fAccountKey := azAccountKey ;
  122. fconAzure.AccountKey := azAccountKey;
  123. end;
  124. end;
  125. procedure TQuickAzure.SetAzureProtocol(azProtocol: TAzureProtocol);
  126. begin
  127. if fAzureProtocol <> azProtocol then
  128. begin
  129. fAzureProtocol := azProtocol;
  130. if azProtocol = azHTTP then fconAzure.Protocol := 'HTTP'
  131. else fconAzure.Protocol := 'HTTPS';
  132. end;
  133. end;
  134. function TQuickAzure.FileToArray(cFilename : string) : TArray<Byte>;
  135. var
  136. fs : TFileStream;
  137. bs : TBytesStream;
  138. begin
  139. fs := TFileStream.Create(cFilename, fmOpenRead);
  140. try
  141. Result := ByteContent(fs);
  142. finally
  143. fs.Free;
  144. end;
  145. end;
  146. function TQuickAzure.StreamToArray(cStream : TStream) : TArray<Byte>;
  147. var
  148. bs : TBytesStream;
  149. begin
  150. bs := TBytesStream.Create(Result);
  151. try
  152. bs.LoadFromStream(cStream);
  153. Result := bs.Bytes;
  154. finally
  155. bs.Free
  156. end;
  157. end;
  158. function TQuickAzure.ByteContent(DataStream: TStream): TBytes;
  159. var
  160. Buffer: TBytes;
  161. begin
  162. if not Assigned(DataStream) then Exit(nil);
  163. SetLength(Buffer, DataStream.Size);
  164. // the content may have been read
  165. DataStream.Position := 0;
  166. if DataStream.Size > 0 then
  167. DataStream.Read(Buffer[0], DataStream.Size);
  168. Result := Buffer;
  169. end;
  170. function TQuickAzure.GMT2DateTime(const gmtdate : string):TDateTime;
  171. function GetMonthDig(Value : string):Integer;
  172. const
  173. aMonth : array[1..12] of string = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
  174. var
  175. idx : Integer;
  176. begin
  177. Result := 0;
  178. for idx := 1 to 12 do
  179. begin
  180. if CompareText(Value,aMonth[idx]) = 0 then
  181. begin
  182. Result := idx;
  183. Break;
  184. end;
  185. end;
  186. end;
  187. var
  188. i : Integer;
  189. Len : Integer;
  190. wDay, wMonth, wYear,
  191. wHour, wMinute, wSec : Word;
  192. begin
  193. //GMT Format: 'Mon, 12 Jan 2014 16:20:35 GMT'
  194. Result := 0;
  195. Len := 0;
  196. if gmtdate = '' then Exit;
  197. try
  198. for i := 0 to Length(gmtdate) do
  199. begin
  200. if gmtdate[i] in ['0'..'9'] then
  201. begin
  202. Len := i;
  203. Break;
  204. end;
  205. end;
  206. //Day
  207. wDay := StrToIntDef(Copy(gmtdate,Len,2),0);
  208. if wDay = 0 then Exit;
  209. Inc(Len,3);
  210. //Month
  211. wMonth := GetMonthDig(Copy(gmtdate,Len,3));
  212. if wMonth = 0 then Exit;
  213. Inc(Len,4);
  214. //Year
  215. wYear := StrToIntDef(Copy(gmtdate,Len,4),0);
  216. if wYear = 0 then Exit;
  217. Inc(Len,5);
  218. //Hour
  219. wHour := StrToIntDef(Copy(gmtdate,Len,2),99);
  220. if wHour = 99 then Exit;
  221. Inc(Len,3);
  222. //Min
  223. wMinute := StrToIntDef(Copy(gmtdate,Len,2),99);
  224. if wMinute = 99 then Exit;
  225. Inc(Len,3);
  226. //Sec
  227. wSec := StrToIntDef(Copy(gmtdate,Len,2),99);
  228. if wSec = 99 then Exit;
  229. Result := EncodeDate(wYear,wMonth,wDay) + EncodeTime(wHour,wMinute,wSec,0);
  230. except
  231. Result := 0;
  232. end;
  233. end;
  234. function GetResponseInfo(ResponseInfo : TCloudResponseInfo) : TAzureResponseInfo;
  235. begin
  236. Result.StatusCode := ResponseInfo.StatusCode;
  237. Result.StatusMsg := ResponseInfo.StatusMessage;
  238. end;
  239. function TQuickAzure.PutBlob(const azContainer, cFilename, azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  240. var
  241. BlobService : TAzureBlobService;
  242. Content : TArray<Byte>;
  243. CloudResponseInfo : TCloudResponseInfo;
  244. container : string;
  245. blobname : string;
  246. begin
  247. BlobService := TAzureBlobService.Create(fconAzure);
  248. try
  249. container := CheckContainer(azContainer);
  250. CloudResponseInfo := TCloudResponseInfo.Create;
  251. try
  252. BlobService.Timeout := fTimeout;
  253. Content := FileToArray(cFilename);
  254. if azBlobName = '' then blobname := cFilename
  255. else blobname := azBlobName;
  256. if blobname.StartsWith('/') then blobname := Copy(blobname,2,Length(blobname));
  257. Result := BlobService.PutBlockBlob(container,blobname,Content,EmptyStr,nil,nil,CloudResponseInfo);
  258. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  259. finally
  260. CloudResponseInfo.Free;
  261. end;
  262. finally
  263. BlobService.Free;
  264. end;
  265. end;
  266. function TQuickAzure.PutBlob(const azContainer : string; cStream : TStream; const azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  267. var
  268. BlobService : TAzureBlobService;
  269. Content : TBytes;
  270. CloudResponseInfo : TCloudResponseInfo;
  271. container : string;
  272. blobname : string;
  273. begin
  274. Result := False;
  275. azResponseInfo.StatusCode := 500;
  276. if cStream.Size = 0 then
  277. begin
  278. azResponseInfo.StatusMsg := 'Stream is empty';
  279. Exit;
  280. end;
  281. container := CheckContainer(azContainer);
  282. blobname := RemoveFirstSlash(azBlobName);
  283. try
  284. BlobService := TAzureBlobService.Create(fconAzure);
  285. try
  286. BlobService.Timeout := fTimeout;
  287. CloudResponseInfo := TCloudResponseInfo.Create;
  288. try
  289. Content := ByteContent(cStream);
  290. Result := BlobService.PutBlockBlob(container,blobname,Content,EmptyStr,nil,nil,CloudResponseInfo);
  291. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  292. finally
  293. CloudResponseInfo.Free;
  294. end;
  295. finally
  296. BlobService.Free;
  297. end;
  298. except
  299. on E : Exception do
  300. begin
  301. azResponseInfo.StatusCode := 500;
  302. azResponseInfo.StatusMsg := e.message;
  303. Result := False;
  304. end;
  305. end;
  306. end;
  307. function TQuickAzure.GetBlob(const azContainer, azBlobName, cFilenameTo : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  308. var
  309. BlobService : TAzureBlobService;
  310. fs : TFileStream;
  311. CloudResponseInfo : TCloudResponseInfo;
  312. container : string;
  313. blobname : string;
  314. begin
  315. container := CheckContainer(azContainer);
  316. blobname := RemoveFirstSlash(azBlobName);
  317. BlobService := TAzureBlobService.Create(fconAzure);
  318. try
  319. BlobService.Timeout := fTimeout;
  320. fs := TFileStream.Create(cFilenameTo,fmCreate);
  321. try
  322. try
  323. CloudResponseInfo := TCloudResponseInfo.Create;
  324. try
  325. Result := BlobService.GetBlob(container,blobname,fs,EmptyStr,CloudResponseInfo);
  326. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  327. finally
  328. CloudResponseInfo.Free;
  329. end;
  330. except
  331. Result := False;
  332. end;
  333. finally
  334. fs.Free;
  335. end;
  336. finally
  337. BlobService.Free;
  338. end;
  339. end;
  340. function TQuickAzure.GetBlob(const azContainer, azBlobName : string; out azResponseInfo : TAzureResponseInfo; out Stream : TMemoryStream) : Boolean;
  341. begin
  342. Stream := TMemoryStream.Create;
  343. try
  344. Result := GetBlob(azContainer,azBlobName,azResponseInfo,TStream(Stream));
  345. except
  346. Stream.Free;
  347. end;
  348. end;
  349. function TQuickAzure.GetBlob(const azContainer, azBlobName : string; out azResponseInfo : TAzureResponseInfo) : TMemoryStream;
  350. begin
  351. GetBlob(azContainer,azBlobName,azResponseInfo,Result);
  352. end;
  353. function TQuickAzure.GetBlob(const azContainer, azBlobName: string; out azResponseInfo: TAzureResponseInfo; var Stream: TStream): Boolean;
  354. var
  355. BlobService : TAzureBlobService;
  356. CloudResponseInfo : TCloudResponseInfo;
  357. container : string;
  358. blobname : string;
  359. begin
  360. container := CheckContainer(azContainer);
  361. blobname := RemoveFirstSlash(azBlobName);
  362. BlobService := TAzureBlobService.Create(fconAzure);
  363. try
  364. BlobService.Timeout := fTimeout;
  365. CloudResponseInfo := TCloudResponseInfo.Create;
  366. try
  367. Result := BlobService.GetBlob(container,blobname,Stream,EmptyStr,CloudResponseInfo);
  368. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  369. finally
  370. CloudResponseInfo.Free;
  371. end;
  372. finally
  373. BlobService.Free;
  374. end;
  375. end;
  376. function TQuickAzure.CheckContainer(const aContainer: string): string;
  377. begin
  378. if aContainer = '' then Result := '$root'
  379. else Result := aContainer;
  380. end;
  381. function TQuickAzure.CopyBlob(const azSourceContainer, azSourceBlobName : string; azTargetContainer, azTargetBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  382. var
  383. BlobService : TAzureBlobService;
  384. CloudResponseInfo : TCloudResponseInfo;
  385. sourcecontainer : string;
  386. targetcontainer : string;
  387. sourceblobname : string;
  388. targetblobname : string;
  389. begin
  390. sourcecontainer := CheckContainer(azSourceContainer);
  391. targetcontainer := CheckContainer(azTargetContainer);
  392. sourceblobname := RemoveFirstSlash(azSourceBlobName);
  393. targetblobname := RemoveFirstSlash(azTargetBlobName);
  394. BlobService := TAzureBlobService.Create(fconAzure);
  395. try
  396. BlobService.Timeout := fTimeout;
  397. try
  398. CloudResponseInfo := TCloudResponseInfo.Create;
  399. try
  400. Result := BlobService.CopyBlob(targetcontainer,targetblobname,sourcecontainer,sourceblobname,'',nil,CloudResponseInfo);
  401. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  402. finally
  403. CloudResponseInfo.Free;
  404. end;
  405. except
  406. on E : Exception do
  407. begin
  408. Result := False;
  409. azResponseInfo.StatusCode := 500;
  410. azResponseInfo.StatusMsg := e.message;
  411. end;
  412. end;
  413. finally
  414. BlobService.Free;
  415. end;
  416. end;
  417. function TQuickAzure.RemoveFirstSlash(const aValue: string): string;
  418. begin
  419. if aValue.StartsWith('/') then Result := Copy(aValue,2,Length(aValue))
  420. else Result := aValue;
  421. end;
  422. function TQuickAzure.RenameBlob(const azContainer, azSourceBlobName, azTargetBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  423. var
  424. sourceblobname : string;
  425. begin
  426. Result := False;
  427. if sourceblobname.Contains('%') then sourceblobname := azSourceBlobName
  428. else sourceblobname := TIdURI.PathEncode(azSourceBlobName);
  429. if CopyBlob(azContainer,sourceblobname,azContainer,azTargetBlobName,azResponseInfo) then
  430. begin
  431. Result := DeleteBlob(azContainer,azSourceBlobName,azResponseInfo);
  432. end;
  433. end;
  434. function TQuickAzure.ExistsObject(const azContainer, azBlobName : string) : Boolean;
  435. var
  436. azBlob : string;
  437. azBlobs : TStrings;
  438. ResponseInfo : TAzureResponseInfo;
  439. begin
  440. Result := False;
  441. azBlobs := ListBlobsNames(azContainer,azBlobName,False,ResponseInfo);
  442. try
  443. if (ResponseInfo.StatusCode = 200) and (Assigned(azBlobs)) then
  444. begin
  445. for azBlob in azBlobs do
  446. begin
  447. if azBlob = azBlobName then
  448. begin
  449. Result := True;
  450. Break;
  451. end;
  452. end;
  453. end;
  454. finally
  455. azBlobs.Free;
  456. end;
  457. end;
  458. function TQuickAzure.ExistsFolder(const azContainer, azFolderName : string) : Boolean;
  459. var
  460. BlobService : TAzureBlobService;
  461. azBlob : TAzureBlob;
  462. azBlobList : TList<TAzureBlob>;
  463. CloudResponseInfo : TCloudResponseInfo;
  464. AzParams : TStrings;
  465. cNextMarker : string;
  466. container : string;
  467. foldername : string;
  468. begin
  469. Result := False;
  470. container := CheckContainer(azContainer);
  471. BlobService := TAzureBlobService.Create(fconAzure);
  472. try
  473. BlobService.Timeout := fTimeout;
  474. AzParams := TStringList.Create;
  475. try
  476. if not azFolderName.EndsWith('/') then foldername := azFolderName + '/'
  477. else foldername := azFolderName;
  478. AzParams.Values['prefix'] := foldername;
  479. AzParams.Values['delimiter'] := '/';
  480. AzParams.Values['maxresults'] := '1';
  481. cNextMarker := '';
  482. CloudResponseInfo := TCloudResponseInfo.Create;
  483. try
  484. azBlobList := BlobService.ListBlobs(container,cNextMarker,AzParams,CloudResponseInfo);
  485. try
  486. if (Assigned(azBlobList)) and (azBlobList.Count > 0) and (CloudResponseInfo.StatusCode = 200) then Result := True;
  487. finally
  488. //frees azbloblist objects
  489. for azBlob in azBlobList do azBlob.Free;
  490. azBlobList.Free;
  491. end;
  492. finally
  493. CloudResponseInfo.Free;
  494. end;
  495. finally
  496. AzParams.Free;
  497. end;
  498. finally
  499. BlobService.Free;
  500. end;
  501. end;
  502. function TQuickAzure.DeleteBlob(const azContainer,azBlobName : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  503. var
  504. BlobService : TAzureBlobService;
  505. CloudResponseInfo : TCloudResponseInfo;
  506. container : string;
  507. blobname : string;
  508. begin
  509. container := CheckContainer(azContainer);
  510. blobname := RemoveFirstSlash(azBlobName);
  511. BlobService := TAzureBlobService.Create(fconAzure);
  512. try
  513. BlobService.Timeout := fTimeout;
  514. CloudResponseInfo := TCloudResponseInfo.Create;
  515. try
  516. Result := BlobService.DeleteBlob(container,blobname,False,EmptyStr,CloudResponseInfo);
  517. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  518. finally
  519. CloudResponseInfo.Free;
  520. end;
  521. finally
  522. BlobService.Free;
  523. end;
  524. end;
  525. {$IFDEF DELPHITOKYO_UP}
  526. function TQuickAzure.ListBlobs(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TBlobList;
  527. var
  528. BlobService : TAzureBlobService;
  529. azBlob : TAzureBlobItem;
  530. azBlobList : TArray<TAzureBlobItem>;
  531. Blob : TAzureBlobObject;
  532. CloudResponseInfo : TCloudResponseInfo;
  533. cNextMarker : string;
  534. container : string;
  535. prefix : string;
  536. blobprefix : TArray<string>;
  537. xmlresp : string;
  538. folder : string;
  539. prop : TPair<string,string>;
  540. begin
  541. Result := TBlobList.Create(True);
  542. cNextMarker := '';
  543. container := CheckContainer(azContainer);
  544. BlobService := TAzureBlobService.Create(fconAzure);
  545. try
  546. if Recursive then prefix := ''
  547. else prefix := '/';
  548. BlobService.Timeout := fTimeout;
  549. repeat
  550. CloudResponseInfo := TCloudResponseInfo.Create;
  551. try
  552. azBlobList := BlobService.ListBlobs(azContainer,azBlobsStartWith,'/',cNextMarker,100,[],cNextMarker,blobprefix,xmlresp,CloudResponseInfo);
  553. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  554. if Assigned(azBlobList) then Result.Capacity := High(azBlobList);
  555. //get folders (prefix)
  556. for folder in blobprefix do
  557. begin
  558. Blob := TAzureBlobObject.Create;
  559. if folder.EndsWith('/') then Blob.Name := RemoveLastChar(folder)
  560. else Blob.Name := folder;
  561. Blob.Name := Copy(Blob.Name,Blob.Name.LastDelimiter('/')+2,Blob.Name.Length);
  562. Blob.IsDir := True;
  563. Result.Add(Blob);
  564. end;
  565. //get files (blobs)
  566. if Assigned(azBlobList) then
  567. begin
  568. for azBlob in azBlobList do
  569. begin
  570. Blob := TAzureBlobObject.Create;
  571. Blob.Name := azBlob.Name;
  572. for prop in azBlob.Properties do
  573. begin
  574. if prop.Key = 'Content-Length' then Blob.Size := StrToInt64Def(prop.Value,0)
  575. else if prop.Key = 'Last-Modified' then Blob.LastModified := GMT2DateTime(prop.Value);
  576. end;
  577. Blob.IsDir := False;
  578. Result.Add(Blob);
  579. end;
  580. end;
  581. finally
  582. CloudResponseInfo.Free;
  583. end;
  584. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  585. finally
  586. BlobService.Free;
  587. end;
  588. end;
  589. {$ELSE}
  590. function TQuickAzure.ListBlobs(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TBlobList;
  591. var
  592. BlobService : TAzureBlobService;
  593. azBlob : TAzureBlob;
  594. azBlobList : TList<TAzureBlob>;
  595. Blob : TAzureBlobObject;
  596. CloudResponseInfo : TCloudResponseInfo;
  597. cNextMarker : string;
  598. AzParams : TStrings;
  599. container : string;
  600. begin
  601. Result := TBlobList.Create(True);
  602. cNextMarker := '';
  603. container := CheckContainer(azContainer);
  604. BlobService := TAzureBlobService.Create(fconAzure);
  605. try
  606. BlobService.Timeout := fTimeout;
  607. repeat
  608. AzParams := TStringList.Create;
  609. try
  610. AzParams.Values['prefix'] := azBlobsStartWith;
  611. if not Recursive then AzParams.Values['delimiter'] := '/';
  612. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  613. CloudResponseInfo := TCloudResponseInfo.Create;
  614. try
  615. azBlobList := BlobService.ListBlobs(container,cNextMarker,AzParams,CloudResponseInfo);
  616. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  617. if Assigned(azBlobList) then
  618. begin
  619. Result.Capacity := High(azBlobList);
  620. try
  621. for azBlob in azBlobList do
  622. begin
  623. Blob := TAzureBlobObject.Create;
  624. Blob.Name := azBlob.Name;
  625. Blob.Size := StrToInt64Def(azBlob.Properties.Values['Content-Length'],0);
  626. Blob.LastModified := GMT2DateTime(azBlob.Properties.Values['Last-Modified']);
  627. Result.Add(Blob);
  628. end;
  629. finally
  630. //frees azbloblist objects
  631. for azBlob in azBlobList do azBlob.Free;
  632. azBlobList.Free;
  633. end;
  634. end;
  635. finally
  636. CloudResponseInfo.Free;
  637. end;
  638. finally
  639. FreeAndNil(AzParams);
  640. end;
  641. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  642. finally
  643. BlobService.Free;
  644. end;
  645. end;
  646. {$ENDIF}
  647. function TQuickAzure.ListBlobsNames(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TStrings;
  648. var
  649. BlobService : TAzureBlobService;
  650. azBlob : TAzureBlob;
  651. azBlobList : TList<TAzureBlob>;
  652. CloudResponseInfo : TCloudResponseInfo;
  653. cNextMarker : string;
  654. AzParams : TStrings;
  655. container : string;
  656. begin
  657. Result := TStringList.Create;
  658. cNextMarker := '';
  659. container := CheckContainer(azContainer);
  660. BlobService := TAzureBlobService.Create(fconAzure);
  661. CloudResponseInfo := TCloudResponseInfo.Create;
  662. try
  663. BlobService.Timeout := fTimeout;
  664. repeat
  665. AzParams := TStringList.Create;
  666. try
  667. AzParams.Values['prefix'] := azBlobsStartWith;
  668. if not Recursive then AzParams.Values['delimiter'] := '/';
  669. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  670. azBlobList := BlobService.ListBlobs(container,cNextMarker,AzParams,CloudResponseInfo);
  671. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  672. if Assigned(azBlobList) then
  673. begin
  674. Result.Capacity := azBlobList.Count;
  675. Result.BeginUpdate;
  676. try
  677. for azBlob in azBlobList do Result.Add(azBlob.Name);
  678. finally
  679. Result.EndUpdate;
  680. //frees bloblist objects
  681. for azBlob in azBlobList do azBlob.Free;
  682. azBlobList.Free;
  683. end;
  684. end;
  685. finally
  686. AzParams.Free;
  687. end;
  688. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  689. finally
  690. BlobService.Free;
  691. CloudResponseInfo.Free;
  692. end;
  693. end;
  694. function TQuickAzure.ExistsContainer(const azContainer : string) : Boolean;
  695. var
  696. Container : string;
  697. Containers : TStrings;
  698. ResponseInfo : TAzureResponseInfo;
  699. begin
  700. Result := False;
  701. Containers := ListContainers(azContainer,ResponseInfo);
  702. try
  703. if (ResponseInfo.StatusCode = 200) and (Assigned(Containers)) then
  704. begin
  705. for Container in Containers do
  706. begin
  707. if Container = azContainer then
  708. begin
  709. Result := True;
  710. Break;
  711. end;
  712. end;
  713. end;
  714. finally
  715. Containers.Free;
  716. end;
  717. end;
  718. function TQuickAzure.ListContainers(const azContainersStartWith : string; out azResponseInfo : TAzureResponseInfo) : TStrings;
  719. var
  720. BlobService : TAzureBlobService;
  721. CloudResponseInfo : TCloudResponseInfo;
  722. cNextMarker : string;
  723. AzParams : TStrings;
  724. AzContainer : TAzureContainer;
  725. AzContainers : TList<TAzureContainer>;
  726. begin
  727. Result := TStringList.Create;
  728. cNextMarker := '';
  729. BlobService := TAzureBlobService.Create(fconAzure);
  730. CloudResponseInfo := TCloudResponseInfo.Create;
  731. try
  732. BlobService.Timeout := fTimeout;
  733. repeat
  734. AzParams := TStringList.Create;
  735. try
  736. if azContainersStartWith <> '' then AzParams.Values['prefix'] := azContainersStartWith;
  737. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  738. AzContainers := BlobService.ListContainers(cNextMarker,AzParams,CloudResponseInfo);
  739. try
  740. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  741. if (azResponseInfo.StatusCode = 200) and (Assigned(AzContainers)) then
  742. begin
  743. Result.Capacity := AzContainers.Count;
  744. for AzContainer in AzContainers do
  745. begin
  746. Result.Add(AzContainer.Name);
  747. end;
  748. end;
  749. finally
  750. if Assigned(AzContainers) then
  751. begin
  752. //frees ContainerList objects
  753. for AzContainer in AzContainers do AzContainer.Free;
  754. AzContainers.Free;
  755. end;
  756. end;
  757. finally
  758. AzParams.Free;
  759. end;
  760. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  761. finally
  762. BlobService.Free;
  763. CloudResponseInfo.Free;
  764. end;
  765. end;
  766. function TQuickAzure.CreateContainer(const azContainer : string; azPublicAccess : TBlobPublicAccess; out azResponseInfo : TAzureResponseInfo) : Boolean;
  767. var
  768. BlobService : TAzureBlobService;
  769. CloudResponseInfo : TCloudResponseInfo;
  770. begin
  771. Result := False;
  772. if azContainer = '' then Exit;
  773. BlobService := TAzureBlobService.Create(fconAzure);
  774. try
  775. BlobService.Timeout := fTimeout;
  776. CloudResponseInfo := TCloudResponseInfo.Create;
  777. try
  778. Result := BlobService.CreateContainer(azContainer,nil,azPublicAccess,CloudResponseInfo);
  779. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  780. finally
  781. CloudResponseInfo.Free;
  782. end;
  783. finally
  784. BlobService.Free;
  785. end;
  786. end;
  787. function TQuickAzure.DeleteContainer(const azContainer : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  788. var
  789. BlobService : TAzureBlobService;
  790. CloudResponseInfo : TCloudResponseInfo;
  791. begin
  792. Result := False;
  793. if azContainer = '' then Exit;
  794. BlobService := TAzureBlobService.Create(fconAzure);
  795. try
  796. BlobService.Timeout := fTimeout;
  797. CloudResponseInfo := TCloudResponseInfo.Create;
  798. try
  799. Result := BlobService.DeleteContainer(azContainer,CloudResponseInfo);
  800. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  801. finally
  802. CloudResponseInfo.Free;
  803. end;
  804. finally
  805. BlobService.Free;
  806. end;
  807. end;
  808. end.