Quick.Azure.pas 29 KB

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