Quick.Amazon.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. { ***************************************************************************
  2. Copyright (c) 2015-2018 Kike Pérez
  3. Unit : Quick.Amazon
  4. Description : Amazon object operations
  5. Author : Kike Pérez
  6. Version : 1.4
  7. Created : 18/11/2016
  8. Modified : 21/02/2018
  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.Amazon;
  22. interface
  23. uses
  24. Classes,
  25. SysUtils,
  26. Generics.Collections,
  27. IPPeerClient,
  28. Data.Cloud.CloudAPI,
  29. Data.Cloud.AmazonAPI;
  30. const
  31. AWSRegionSet : array of string = [
  32. 'eu-west-1',
  33. 'eu-west-1',
  34. 'eu-central-1',
  35. 'us-east-1',
  36. 'us-west-1',
  37. 'us-west-2',
  38. 'ap-southeast-1',
  39. 'ap-southeast-2',
  40. 'ap-northeast-1',
  41. 'ap-northeast-2',
  42. 'sa-east-1',
  43. 'us-east-1', // deprecate
  44. 'us-east-1','us-east-1'];
  45. type
  46. TAmazonProtocol = (amHTTP,amHTTPS);
  47. TAmazonStorage = TAmazonStorageService;
  48. TAmazonACLAccess = TAmazonACLType;
  49. TAmazonRegion = Data.Cloud.AmazonAPI.TAmazonRegion;
  50. TAmazonObject = class
  51. Name : string;
  52. Modified : TDateTime;
  53. Size : Int64;
  54. IsDeleted : Boolean;
  55. end;
  56. TAmazonObjects = class(TObjectList<TAmazonObject>);
  57. TAmazonResponseInfo = record
  58. StatusCode : Integer;
  59. StatusMsg : string;
  60. end;
  61. TQuickAmazon = class
  62. private
  63. fconAmazon : TAmazonConnectionInfo;
  64. fAccountName : string;
  65. fAccountKey : string;
  66. fAWSRegion : TAmazonRegion;
  67. fAmazonProtocol : TAmazonProtocol;
  68. procedure SetAccountName(amAccountName : string);
  69. procedure SetAccountKey(amAccountKey : string);
  70. procedure SetAmazonProtocol(amProtocol : TAmazonProtocol);
  71. procedure SetAWSRegion(Value : TAmazonRegion);
  72. function FileToArray(cFilename : string) : TArray<Byte>;
  73. function StreamToArray(cStream : TStream) : TArray<Byte>;
  74. public
  75. constructor Create; overload;
  76. constructor Create(amAccountName, amAccountKey : string); overload;
  77. destructor Destroy; override;
  78. property AccountName : string read fAccountName write SetAccountName;
  79. property AccountKey : string read fAccountKey write SetAccountKey;
  80. property AmazonProtocol : TAmazonProtocol read fAmazonProtocol write SetAmazonProtocol;
  81. property AWSRegion : TAmazonRegion read fAWSRegion write SetAWSRegion;
  82. function StorageURL(amBucket : string) : string;
  83. function PutObject(amBucket, cFilename, amObjectName : string; amACLType : TAmazonACLType; var amResponseInfo : TAmazonResponseInfo) : Boolean; overload;
  84. function PutObject(amBucket : string; cStream : TStream; amObjectName : string; amACLType : TAmazonACLType; var amResponseInfo : TAmazonResponseInfo) : Boolean; overload;
  85. function GetObject(amBucket, amObjectName, cFilenameTo : string; var amResponseInfo : TAmazonResponseInfo) : Boolean; overload;
  86. function GetObject(amBucket, amObjectName : string; var amResponseInfo : TAmazonResponseInfo) : TMemoryStream; overload;
  87. function ExistsObject(amBucket, amObjectName : string; amRegion : TAmazonRegion) : Boolean;
  88. function DeleteObject(amBucket,amObjectName : string; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  89. function ListObjects(amBucket : string; amObjectsStartWith : string; amRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : TAmazonObjects;
  90. function ListObjectsNames(amBucket : string; amObjectsStartWith : string; amRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : TStrings;
  91. function ExistsBucket(amBucketName : string) : Boolean;
  92. function ListBuckets(var amResponseInfo : TAmazonResponseInfo) : TStrings;
  93. function CreateBucket(amBucket : string; amBucketRegion : TAmazonRegion; amACLType : TAmazonACLAccess; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  94. function DeleteBucket(amBucket : string; amBucketRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  95. class function GetAWSRegion(Region: TAmazonRegion): string; overload;
  96. class function GetAWSRegion(const Region : string) : TAmazonRegion; overload;
  97. end;
  98. implementation
  99. constructor TQuickAmazon.Create;
  100. begin
  101. inherited;
  102. fconAmazon := TAmazonConnectionInfo.Create(nil);
  103. fAmazonProtocol := amHTTP;
  104. fconAmazon.UseDefaultEndpoints := False;
  105. end;
  106. constructor TQuickAmazon.Create(amAccountName, amAccountKey : string);
  107. begin
  108. Create;
  109. SetAccountName(amAccountName);
  110. SetAccountKey(amAccountKey);
  111. end;
  112. destructor TQuickAmazon.Destroy;
  113. begin
  114. if Assigned(fconAmazon) then fconAmazon.Free;
  115. inherited;
  116. end;
  117. procedure TQuickAmazon.SetAWSRegion(Value : TAmazonRegion);
  118. begin
  119. fAWSRegion := Value;
  120. fconAmazon.StorageEndpoint := Format('s3-%s.amazonaws.com',[GetAWSRegion(Value)]);
  121. end;
  122. procedure TQuickAmazon.SetAccountName(amAccountName : string);
  123. begin
  124. if fAccountName <> amAccountName then
  125. begin
  126. fAccountName := amAccountName;
  127. fconAmazon.AccountName := amAccountName;
  128. end;
  129. end;
  130. procedure TQuickAmazon.SetAccountKey(amAccountKey : string);
  131. begin
  132. if fAccountKey <> amAccountKey then
  133. begin
  134. fAccountKey := amAccountKey ;
  135. fconAmazon.AccountKey := amAccountKey;
  136. end;
  137. end;
  138. procedure TQuickAmazon.SetAmazonProtocol(amProtocol: TAmazonProtocol);
  139. begin
  140. if fAmazonProtocol <> amProtocol then
  141. begin
  142. fAmazonProtocol := amProtocol;
  143. if amProtocol = amHTTP then fconAmazon.Protocol := 'http'
  144. else fconAmazon.Protocol := 'https';
  145. end;
  146. end;
  147. function TQuickAmazon.FileToArray(cFilename : string) : TArray<Byte>;
  148. var
  149. fs : TFileStream;
  150. bs : TBytesStream;
  151. begin
  152. fs := TFileStream.Create(cFilename, fmOpenRead);
  153. try
  154. bs := TBytesStream.Create(Result);
  155. try
  156. bs.LoadFromStream(fs);
  157. Result := bs.Bytes;
  158. finally
  159. bs.Free
  160. end;
  161. finally
  162. fs.Free;
  163. end;
  164. end;
  165. function TQuickAmazon.StreamToArray(cStream : TStream) : TArray<Byte>;
  166. var
  167. bs : TBytesStream;
  168. begin
  169. bs := TBytesStream.Create(Result);
  170. try
  171. bs.LoadFromStream(cStream);
  172. Result := bs.Bytes;
  173. finally
  174. bs.Free
  175. end;
  176. end;
  177. {function TQuickAmazon.StreamToArray(cStream : TStream) : TArray<Byte>;
  178. begin
  179. SetLength(Result,cStream.Size);
  180. cStream.WriteData(Result,Length(Result));
  181. end;}
  182. function GetResponseInfo(amResponseInfo : TCloudResponseInfo) : TAmazonResponseInfo;
  183. begin
  184. Result.StatusCode := amResponseInfo.StatusCode;
  185. Result.StatusMsg := amResponseInfo.StatusMessage;
  186. end;
  187. function TQuickAmazon.StorageURL(amBucket : string) : string;
  188. begin
  189. Result := fconAmazon.StorageURL(amBucket)
  190. end;
  191. function TQuickAmazon.PutObject(amBucket, cFilename, amObjectName : string; amACLType : TAmazonACLType; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  192. var
  193. AmazonS3 : TAmazonStorage;
  194. Content : TArray<Byte>;
  195. CloudResponseInfo : TCloudResponseInfo;
  196. begin
  197. Result := False;
  198. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  199. if amBucket = '' then amBucket := '$root';
  200. CloudResponseInfo := TCloudResponseInfo.Create;
  201. try
  202. Content := FileToArray(cFilename);
  203. if amObjectName = '' then amObjectName := cFilename;
  204. if amObjectName.StartsWith('/') then amObjectName := Copy(amObjectName,2,Length(amObjectName));
  205. Result := AmazonS3.UploadObject(amBucket,amObjectName,Content,False,nil,nil,amACLType,CloudResponseInfo);
  206. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  207. finally
  208. AmazonS3.Free;
  209. CloudResponseInfo.Free;
  210. end;
  211. end;
  212. function TQuickAmazon.PutObject(amBucket : string; cStream : TStream; amObjectName : string; amACLType : TAmazonACLType; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  213. var
  214. AmazonS3 : TAmazonStorage;
  215. Content : TArray<Byte>;
  216. CloudResponseInfo : TCloudResponseInfo;
  217. begin
  218. amResponseInfo.StatusCode := 500;
  219. if amBucket = '' then amBucket := '$root';
  220. if amObjectName.StartsWith('/') then amObjectName := Copy(amObjectName,2,Length(amObjectName));
  221. try
  222. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  223. try
  224. //AmazonS3.Timeout := fTimeout;
  225. CloudResponseInfo := TCloudResponseInfo.Create;
  226. //CloudResponseInfo.Headers.AddPair();
  227. Content := StreamToArray(cStream);
  228. Result := AmazonS3.UploadObject(amBucket,amObjectName,Content,False,nil,nil,amACLType,CloudResponseInfo);
  229. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  230. finally
  231. AmazonS3.Free;
  232. CloudResponseInfo.Free;
  233. SetLength(Content,0);
  234. Content := nil;
  235. end;
  236. except
  237. Result := False;
  238. end;
  239. end;
  240. function TQuickAmazon.GetObject(amBucket, amObjectName, cFilenameTo : string; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  241. var
  242. AmazonS3 : TAmazonStorage;
  243. fs : TFileStream;
  244. CloudResponseInfo : TCloudResponseInfo;
  245. amParams : TAmazonGetObjectOptionals;
  246. begin
  247. Result := False;
  248. if amBucket = '' then amBucket := '$root';
  249. if amObjectName.StartsWith('/') then amObjectName := Copy(amObjectName,2,Length(amObjectName));
  250. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  251. try
  252. //AmazonS3.Timeout := fTimeout;
  253. CloudResponseInfo := TCloudResponseInfo.Create;
  254. if FileExists(cFilenameTo) then fs := TFileStream.Create(cFilenameTo,fmOpenWrite)
  255. else fs := TFileStream.Create(cFilenameTo,fmCreate);
  256. try
  257. try
  258. AmazonS3.GetObject(amBucket,amObjectName,fs,CloudResponseInfo);
  259. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  260. if amResponseInfo.StatusCode = 200 then Result := True;
  261. except
  262. Result := False;
  263. end;
  264. finally
  265. fs.Free;
  266. CloudResponseInfo.Free;
  267. end;
  268. finally
  269. AmazonS3.Free;
  270. end;
  271. end;
  272. function TQuickAmazon.GetObject(amBucket, amObjectName : string; var amResponseInfo : TAmazonResponseInfo) : TMemoryStream;
  273. var
  274. AmazonS3 : TAmazonStorage;
  275. fs : TFileStream;
  276. CloudResponseInfo : TCloudResponseInfo;
  277. begin
  278. Result := TMemoryStream.Create;
  279. if amBucket = '' then amBucket := '$root';
  280. if amObjectName.StartsWith('/') then amObjectName := Copy(amObjectName,2,Length(amObjectName));
  281. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  282. try
  283. //AmazonS3.Timeout := fTimeout;
  284. CloudResponseInfo := TCloudResponseInfo.Create;
  285. try
  286. AmazonS3.GetObject(amBucket,amObjectName,Result,CloudResponseInfo);
  287. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  288. except
  289. Result := nil;
  290. end;
  291. finally
  292. AmazonS3.Free;
  293. CloudResponseInfo.Free;
  294. end;
  295. end;
  296. function TQuickAmazon.ExistsObject(amBucket, amObjectName : string; amRegion : TAmazonRegion) : Boolean;
  297. var
  298. amObject : string;
  299. amObjects : TStrings;
  300. ResponseInfo : TAmazonResponseInfo;
  301. begin
  302. Result := False;
  303. amObjects := ListObjectsNames(amBucket,amObjectName,amRegion,ResponseInfo);
  304. try
  305. if (ResponseInfo.StatusCode = 200) and (Assigned(amObjects)) then
  306. begin
  307. for amObject in amObjects do
  308. begin
  309. if amObject = amObjectName then
  310. begin
  311. Result := True;
  312. Break;
  313. end;
  314. end;
  315. end;
  316. finally
  317. amObjects.Free;
  318. end;
  319. end;
  320. function TQuickAmazon.DeleteObject(amBucket,amObjectName : string; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  321. var
  322. AmazonS3 : TAmazonStorage;
  323. CloudResponseInfo : TCloudResponseInfo;
  324. begin
  325. Result := False;
  326. if amBucket = '' then amBucket := '$root';
  327. if amObjectName.StartsWith('/') then amObjectName := Copy(amObjectName,2,Length(amObjectName));
  328. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  329. try
  330. //AmazonS3.Timeout := fTimeout;
  331. CloudResponseInfo := TCloudResponseInfo.Create;
  332. Result := AmazonS3.DeleteObject(amBucket,amObjectName,CloudResponseInfo);
  333. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  334. finally
  335. AmazonS3.Free;
  336. CloudResponseInfo.Free;
  337. end;
  338. end;
  339. function TQuickAmazon.ListObjects(amBucket : string; amObjectsStartWith : string; amRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : TAmazonObjects;
  340. var
  341. AmazonS3 : TAmazonStorage;
  342. amObject : TAmazonObject;
  343. i : Integer;
  344. amBucketResult : TAmazonBucketResult;
  345. CloudResponseInfo : TCloudResponseInfo;
  346. cNextMarker : string;
  347. amParams : TStrings;
  348. a : TAmazonBucketResult;
  349. begin
  350. Result := TAmazonObjects.Create(True);
  351. cNextMarker := '';
  352. if amBucket = '' then amBucket := '$root';
  353. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  354. CloudResponseInfo := TCloudResponseInfo.Create;
  355. try
  356. //AmazonS3.Timeout := fTimeout;
  357. repeat
  358. amParams := TStringList.Create;
  359. try
  360. amParams.Values['prefix'] := amObjectsStartWith;
  361. if cNextMarker <> '' then amParams.Values['marker'] := cNextMarker;
  362. amBucketResult := AmazonS3.GetBucket(amBucket,amParams,CloudResponseInfo,amRegion);
  363. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  364. if Assigned(amBucketResult) then
  365. begin
  366. try
  367. for i := 0 to amBucketResult.Objects.Count-1 do
  368. begin
  369. amObject := TAmazonObject.Create;
  370. amObject.Name := amBucketResult.Objects[i].Name;
  371. amObject.Modified := StrToDateTime(amBucketResult.Objects[i].LastModified);
  372. amObject.Size := amBucketResult.Objects[i].Size;
  373. amObject.IsDeleted := amBucketResult.Objects[i].IsDeleted;
  374. Result.Add(amObject);
  375. end;
  376. finally
  377. amBucketResult.Free;
  378. end;
  379. cNextMarker := amBucketResult.Marker;
  380. end;
  381. finally
  382. amParams.Free;
  383. end;
  384. until (cNextMarker = '') or (amResponseInfo.StatusCode <> 200);
  385. finally
  386. AmazonS3.Free;
  387. CloudResponseInfo.Free;
  388. end;
  389. end;
  390. function TQuickAmazon.ListObjectsNames(amBucket : string; amObjectsStartWith : string; amRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : TStrings;
  391. var
  392. AmazonS3 : TAmazonStorage;
  393. i : Integer;
  394. amBucketResult : TAmazonBucketResult;
  395. CloudResponseInfo : TCloudResponseInfo;
  396. cNextMarker : string;
  397. amParams : TStrings;
  398. a : TAmazonBucketResult;
  399. begin
  400. Result := TStringList.Create;
  401. cNextMarker := '';
  402. if amBucket = '' then amBucket := '$root';
  403. AmazonS3 := TAmazonStorage.Create(fconAmazon);
  404. CloudResponseInfo := TCloudResponseInfo.Create;
  405. try
  406. //AmazonS3.Timeout := fTimeout;
  407. repeat
  408. amParams := TStringList.Create;
  409. try
  410. if amObjectsStartWith <> '' then amParams.Values['prefix'] := amObjectsStartWith;
  411. if cNextMarker <> '' then amParams.Values['marker'] := cNextMarker;
  412. amBucketResult := AmazonS3.GetBucket(amBucket,amParams,CloudResponseInfo,amRegion);
  413. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  414. if Assigned(amBucketResult) then
  415. begin
  416. try
  417. for i := 0 to amBucketResult.Objects.Count-1 do Result.Add(amBucketResult.Objects[i].Name);
  418. finally
  419. amBucketResult.Free;
  420. end;
  421. cNextMarker := amBucketResult.Marker;
  422. end;
  423. finally
  424. amParams.Free;
  425. end;
  426. until (cNextMarker = '') or (amResponseInfo.StatusCode <> 200);
  427. finally
  428. AmazonS3.Free;
  429. CloudResponseInfo.Free;
  430. end;
  431. end;
  432. function TQuickAmazon.ExistsBucket(amBucketName : string) : Boolean;
  433. var
  434. amBucket : string;
  435. amBuckets : TStrings;
  436. ResponseInfo : TAmazonResponseInfo;
  437. begin
  438. Result := False;
  439. amBuckets := ListBuckets(ResponseInfo);
  440. try
  441. if (ResponseInfo.StatusCode = 200) and (Assigned(amBuckets)) then
  442. begin
  443. for amBucket in amBuckets do
  444. begin
  445. if amBucket = amBucketName then
  446. begin
  447. Result := True;
  448. Break;
  449. end;
  450. end;
  451. end;
  452. finally
  453. amBuckets.Free;
  454. end;
  455. end;
  456. function TQuickAmazon.ListBuckets(var amResponseInfo : TAmazonResponseInfo) : TStrings;
  457. var
  458. AmazonS3 : TAmazonStorageService;
  459. CloudResponseInfo : TCloudResponseInfo;
  460. Buckets : TStrings;
  461. i : Integer;
  462. begin
  463. AmazonS3 := TAmazonStorageService.Create(fconAmazon);
  464. Result := TStringList.Create;
  465. try
  466. //AmazonS3.Timeout := fTimeout;
  467. CloudResponseInfo := TCloudResponseInfo.Create;
  468. Buckets := AmazonS3.ListBuckets(CloudResponseInfo);
  469. try
  470. for i := 0 to Buckets.Count -1 do
  471. begin
  472. Result.Add(Buckets.Names[i]);
  473. end;
  474. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  475. finally
  476. Buckets.Free;
  477. end;
  478. finally
  479. AmazonS3.Free;
  480. CloudResponseInfo.Free;
  481. end;
  482. end;
  483. function TQuickAmazon.CreateBucket(amBucket : string; amBucketRegion : TAmazonRegion; amACLType : TAmazonACLAccess; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  484. var
  485. AmazonS3 : TAmazonStorageService;
  486. CloudResponseInfo : TCloudResponseInfo;
  487. begin
  488. Result := False;
  489. if amBucket = '' then Exit;
  490. AmazonS3 := TAmazonStorageService.Create(fconAmazon);
  491. try
  492. CloudResponseInfo := TCloudResponseInfo.Create;
  493. Result := AmazonS3.CreateBucket(amBucket,amACLType,amBucketRegion,CloudResponseInfo);
  494. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  495. finally
  496. AmazonS3.Free;
  497. CloudResponseInfo.Free;
  498. end;
  499. end;
  500. function TQuickAmazon.DeleteBucket(amBucket : string; amBucketRegion : TAmazonRegion; var amResponseInfo : TAmazonResponseInfo) : Boolean;
  501. var
  502. AmazonS3 : TAmazonStorageService;
  503. CloudResponseInfo : TCloudResponseInfo;
  504. begin
  505. Result := False;
  506. if amBucket = '' then Exit;
  507. AmazonS3 := TAmazonStorageService.Create(fconAmazon);
  508. try
  509. CloudResponseInfo := TCloudResponseInfo.Create;
  510. Result := AmazonS3.DeleteBucket(amBucket,CloudResponseInfo,amBucketRegion);
  511. amResponseInfo := GetResponseInfo(CloudResponseInfo);
  512. finally
  513. AmazonS3.Free;
  514. CloudResponseInfo.Free;
  515. end;
  516. end;
  517. class function TQuickAmazon.GetAWSRegion(const Region : string) : TAmazonRegion;
  518. begin
  519. Result := TAmazonStorageService.GetRegionFromString(Region);
  520. end;
  521. class function TQuickAmazon.GetAWSRegion(Region: TAmazonRegion): string;
  522. begin
  523. Result := TAmazonStorageService.GetRegionString(Region);
  524. end;
  525. end.