Quick.Azure.pas 27 KB

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