Quick.Azure.pas 26 KB

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