/// <summary>Copies object to another.</summary>
        /// <param name="sourceObject">Source object info.</param>
        /// <param name="destObject">Destination object info.</param>
        public void CopyObjects(IS3ObjectInfo sourceObject, IS3ObjectInfo destObject)
        {
            string            pathFromObjectKey = PathHelper.GetPathFromObjectKey(destObject.Key, true);
            CopyObjectRequest request           = new CopyObjectRequest()
            {
                SourceBucket      = sourceObject.BucketName,
                DestinationBucket = GetBucketName(pathFromObjectKey),
                SourceKey         = sourceObject.Key,
                DestinationKey    = destObject.Key
            };

            if (this.IsPublicAccess(pathFromObjectKey))
            {
                request.CannedACL = S3CannedACL.PublicRead;
            }
            CopyObjectResponse copyObjectResponse = this.S3Client.CopyObject(request);

            destObject.ETag   = copyObjectResponse.ETag;
            destObject.Length = ValidationHelper.GetLong(copyObjectResponse.ContentLength, 0L);
            FileDebug.LogFileOperation(PathHelper.GetPathFromObjectKey(sourceObject.Key, true) + "|" + PathHelper.GetPathFromObjectKey(destObject.Key, true), nameof(CopyObjects), "Custom Amazon");
            RemoveRequestCache(destObject.Key);
        }
 /// <summary>Remove S3 file from temporary local storage.</summary>
 /// <param name="obj">S3 object to be removed from temporary local storage</param>
 private static void RemoveFromTemp(IS3ObjectInfo obj)
 {
     DeleteFileFromLocalPath(CMS.IO.Path.Combine(PathHelper.TempPath, PathHelper.GetPathFromObjectKey(obj.Key, false)));
 }
        /// <summary>
        /// Returns list with objects from given bucket and under given path.
        /// </summary>
        /// <param name="path">Path.</param>
        /// <param name="type">Specifies which objects are returned (files, directories, both).</param>
        /// <param name="useFlatListing">Whether flat listing is used (all files from all subdirectories all in the result).</param>
        /// <param name="lower">Specifies whether path should be lowered inside method.</param>
        /// <param name="useCache">Indicates if results should be primary taken from cache to get better performance</param>
        /// <remarks>
        /// In order to allow to distinguish between files and directories, directories are listed with a trailing backslash.
        /// </remarks>
        public List <string> GetObjectsList(string path, ObjectTypeEnum type, bool useFlatListing = false, bool lower = true, bool useCache = true)
        {
            string bucketName = GetBucketName(path);

            if (string.IsNullOrEmpty(bucketName))
            {
                return(null);
            }
            var request = new ListObjectsRequest
            {
                BucketName = bucketName
            };

            if (!string.IsNullOrEmpty(path))
            {
                request.Prefix = PathHelper.GetObjectKeyFromPath(path).TrimEnd('/') + "/";
            }
            if (!useFlatListing)
            {
                request.Delimiter = "/";
            }
            var    source1 = new HashSet <string>();
            string key     = $"{request.Prefix }|{type.ToString("F")}|{useFlatListing}|{lower}";

            if (useCache && AbstractStockHelper <RequestStockHelper> .Contains(STORAGE_KEY, key, false))
            {
                CMS.IO.Directory.LogDirectoryOperation(path, "GetObjectListFromCache", "Custom Amazon");
                var source2 = AbstractStockHelper <RequestStockHelper> .GetItem(STORAGE_KEY, key, false) as HashSet <string>;

                if (source2 == null)
                {
                    return(new List <string>());
                }
                return(source2.ToList());
            }
            ListObjectsResponse listObjectsResponse;

            do
            {
                listObjectsResponse = this.S3Client.ListObjects(request);
                if (type == ObjectTypeEnum.Directories && !useFlatListing)
                {
                    foreach (string commonPrefix in listObjectsResponse.CommonPrefixes)
                    {
                        source1.Add($"{path}\\{CMS.IO.Path.GetFileName(commonPrefix.TrimEnd('/'))}\\");
                    }
                }
                else
                {
                    bool isDirectory = type == ObjectTypeEnum.FilesAndDirectories || type == ObjectTypeEnum.Directories;
                    bool isFile      = type == ObjectTypeEnum.FilesAndDirectories || type == ObjectTypeEnum.Files;
                    foreach (S3Object s3Object in listObjectsResponse.S3Objects)
                    {
                        bool directory = s3Object.Key.EndsWith("/", StringComparison.Ordinal);
                        if (directory && isDirectory || !directory && isFile)
                        {
                            source1.Add(PathHelper.GetPathFromObjectKey(s3Object.Key, true, directory, lower));
                        }
                    }
                }
                if (listObjectsResponse.IsTruncated)
                {
                    request.Marker = listObjectsResponse.NextMarker;
                }
            }while (listObjectsResponse.IsTruncated);
            source1.Remove(PathHelper.GetPathFromObjectKey(request.Prefix, true, true, lower));
            CMS.IO.Directory.LogDirectoryOperation(path, "ListObjects", "Custom Amazon");
            AbstractStockHelper <RequestStockHelper> .AddToStorage(STORAGE_KEY, key, (object)source1, false);

            return(source1.ToList());
        }