Quick.Azure.pas 29 KB

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