Quick.Azure.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  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 : 02/03/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. //get folders (prefix)
  552. for folder in blobprefix do
  553. begin
  554. Blob := TAzureBlobObject.Create;
  555. if folder.EndsWith('/') then Blob.Name := RemoveLastChar(folder)
  556. else Blob.Name := folder;
  557. Blob.Name := Copy(Blob.Name,Blob.Name.LastDelimiter('/')+2,Blob.Name.Length);
  558. Blob.IsDir := True;
  559. Result.Add(Blob);
  560. end;
  561. //get files (blobs)
  562. if Assigned(azBlobList) then
  563. begin
  564. for azBlob in azBlobList do
  565. begin
  566. Blob := TAzureBlobObject.Create;
  567. Blob.Name := azBlob.Name;
  568. for prop in azBlob.Properties do
  569. begin
  570. if prop.Key = 'Content-Length' then Blob.Size := StrToInt64Def(prop.Value,0)
  571. else if prop.Key = 'Last-Modified' then Blob.LastModified := GMT2DateTime(prop.Value);
  572. end;
  573. Blob.IsDir := False;
  574. Result.Add(Blob);
  575. end;
  576. end;
  577. finally
  578. CloudResponseInfo.Free;
  579. end;
  580. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  581. finally
  582. BlobService.Free;
  583. end;
  584. end;
  585. {$ELSE}
  586. function TQuickAzure.ListBlobs(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TBlobList;
  587. var
  588. BlobService : TAzureBlobService;
  589. azBlob : TAzureBlob;
  590. azBlobList : TList<TAzureBlob>;
  591. Blob : TAzureBlobObject;
  592. CloudResponseInfo : TCloudResponseInfo;
  593. cNextMarker : string;
  594. AzParams : TStrings;
  595. container : string;
  596. begin
  597. Result := TBlobList.Create(True);
  598. cNextMarker := '';
  599. container := CheckContainer(azContainer);
  600. BlobService := TAzureBlobService.Create(fconAzure);
  601. try
  602. BlobService.Timeout := fTimeout;
  603. repeat
  604. AzParams := TStringList.Create;
  605. try
  606. AzParams.Values['prefix'] := azBlobsStartWith;
  607. if not Recursive then AzParams.Values['delimiter'] := '/';
  608. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  609. CloudResponseInfo := TCloudResponseInfo.Create;
  610. try
  611. azBlobList := BlobService.ListBlobs(container,cNextMarker,AzParams,CloudResponseInfo);
  612. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  613. if Assigned(azBlobList) then
  614. begin
  615. try
  616. for azBlob in azBlobList do
  617. begin
  618. Blob := TAzureBlobObject.Create;
  619. Blob.Name := azBlob.Name;
  620. Blob.Size := StrToInt64Def(azBlob.Properties.Values['Content-Length'],0);
  621. Blob.LastModified := GMT2DateTime(azBlob.Properties.Values['Last-Modified']);
  622. Result.Add(Blob);
  623. end;
  624. finally
  625. //frees azbloblist objects
  626. for azBlob in azBlobList do azBlob.Free;
  627. azBlobList.Free;
  628. end;
  629. end;
  630. finally
  631. CloudResponseInfo.Free;
  632. end;
  633. finally
  634. FreeAndNil(AzParams);
  635. end;
  636. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  637. finally
  638. BlobService.Free;
  639. end;
  640. end;
  641. {$ENDIF}
  642. function TQuickAzure.ListBlobsNames(const azContainer, azBlobsStartWith : string; Recursive : Boolean; out azResponseInfo : TAzureResponseInfo) : TStrings;
  643. var
  644. BlobService : TAzureBlobService;
  645. azBlob : TAzureBlob;
  646. azBlobList : TList<TAzureBlob>;
  647. CloudResponseInfo : TCloudResponseInfo;
  648. cNextMarker : string;
  649. AzParams : TStrings;
  650. container : string;
  651. begin
  652. Result := TStringList.Create;
  653. cNextMarker := '';
  654. container := CheckContainer(azContainer);
  655. BlobService := TAzureBlobService.Create(fconAzure);
  656. CloudResponseInfo := TCloudResponseInfo.Create;
  657. try
  658. BlobService.Timeout := fTimeout;
  659. repeat
  660. AzParams := TStringList.Create;
  661. try
  662. AzParams.Values['prefix'] := azBlobsStartWith;
  663. if not Recursive then AzParams.Values['delimiter'] := '/';
  664. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  665. azBlobList := BlobService.ListBlobs(container,cNextMarker,AzParams,CloudResponseInfo);
  666. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  667. if Assigned(azBlobList) then
  668. begin
  669. Result.BeginUpdate;
  670. try
  671. for azBlob in azBlobList do Result.Add(azBlob.Name);
  672. finally
  673. Result.EndUpdate;
  674. //frees bloblist objects
  675. for azBlob in azBlobList do azBlob.Free;
  676. azBlobList.Free;
  677. end;
  678. end;
  679. finally
  680. AzParams.Free;
  681. end;
  682. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  683. finally
  684. BlobService.Free;
  685. CloudResponseInfo.Free;
  686. end;
  687. end;
  688. function TQuickAzure.ExistsContainer(const azContainer : string) : Boolean;
  689. var
  690. Container : string;
  691. Containers : TStrings;
  692. ResponseInfo : TAzureResponseInfo;
  693. begin
  694. Result := False;
  695. Containers := ListContainers(azContainer,ResponseInfo);
  696. try
  697. if (ResponseInfo.StatusCode = 200) and (Assigned(Containers)) then
  698. begin
  699. for Container in Containers do
  700. begin
  701. if Container = azContainer then
  702. begin
  703. Result := True;
  704. Break;
  705. end;
  706. end;
  707. end;
  708. finally
  709. Containers.Free;
  710. end;
  711. end;
  712. function TQuickAzure.ListContainers(const azContainersStartWith : string; out azResponseInfo : TAzureResponseInfo) : TStrings;
  713. var
  714. BlobService : TAzureBlobService;
  715. CloudResponseInfo : TCloudResponseInfo;
  716. cNextMarker : string;
  717. AzParams : TStrings;
  718. AzContainer : TAzureContainer;
  719. AzContainers : TList<TAzureContainer>;
  720. begin
  721. Result := TStringList.Create;
  722. cNextMarker := '';
  723. BlobService := TAzureBlobService.Create(fconAzure);
  724. CloudResponseInfo := TCloudResponseInfo.Create;
  725. try
  726. BlobService.Timeout := fTimeout;
  727. repeat
  728. AzParams := TStringList.Create;
  729. try
  730. if azContainersStartWith <> '' then AzParams.Values['prefix'] := azContainersStartWith;
  731. if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
  732. AzContainers := BlobService.ListContainers(cNextMarker,AzParams,CloudResponseInfo);
  733. try
  734. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  735. if (azResponseInfo.StatusCode = 200) and (Assigned(AzContainers)) then
  736. begin
  737. for AzContainer in AzContainers do
  738. begin
  739. Result.Add(AzContainer.Name);
  740. end;
  741. end;
  742. finally
  743. if Assigned(AzContainers) then
  744. begin
  745. //frees ContainerList objects
  746. for AzContainer in AzContainers do AzContainer.Free;
  747. AzContainers.Free;
  748. end;
  749. end;
  750. finally
  751. AzParams.Free;
  752. end;
  753. until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
  754. finally
  755. BlobService.Free;
  756. CloudResponseInfo.Free;
  757. end;
  758. end;
  759. function TQuickAzure.CreateContainer(const azContainer : string; azPublicAccess : TBlobPublicAccess; out azResponseInfo : TAzureResponseInfo) : Boolean;
  760. var
  761. BlobService : TAzureBlobService;
  762. CloudResponseInfo : TCloudResponseInfo;
  763. begin
  764. Result := False;
  765. if azContainer = '' then Exit;
  766. BlobService := TAzureBlobService.Create(fconAzure);
  767. try
  768. BlobService.Timeout := fTimeout;
  769. CloudResponseInfo := TCloudResponseInfo.Create;
  770. Result := BlobService.CreateContainer(azContainer,nil,azPublicAccess,CloudResponseInfo);
  771. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  772. finally
  773. BlobService.Free;
  774. CloudResponseInfo.Free;
  775. end;
  776. end;
  777. function TQuickAzure.DeleteContainer(const azContainer : string; out azResponseInfo : TAzureResponseInfo) : Boolean;
  778. var
  779. BlobService : TAzureBlobService;
  780. CloudResponseInfo : TCloudResponseInfo;
  781. begin
  782. Result := False;
  783. if azContainer = '' then Exit;
  784. BlobService := TAzureBlobService.Create(fconAzure);
  785. try
  786. BlobService.Timeout := fTimeout;
  787. CloudResponseInfo := TCloudResponseInfo.Create;
  788. Result := BlobService.DeleteContainer(azContainer,CloudResponseInfo);
  789. azResponseInfo := GetResponseInfo(CloudResponseInfo);
  790. finally
  791. BlobService.Free;
  792. CloudResponseInfo.Free;
  793. end;
  794. end;
  795. end.