/// <summary>Deletes files and optionally directories in given path.</summary> /// <param name="path">Path to delete.</param> /// <param name="directories">Indicates, whether directories should be also deleted.</param> private void DeleteInternal(string path, bool directories) { path = PathHelper.GetValidPath(path); var keyVersions = this.Provider .GetObjectsList(path, directories ? ObjectTypeEnum.FilesAndDirectories : ObjectTypeEnum.Files, true, true, false) .ConvertAll(p => new KeyVersion() { Key = PathHelper.GetObjectKeyFromPath(p, true) }) .Batch(S3ObjectInfoProvider.MAX_OBJECTS_PER_REQUEST); foreach (IEnumerable <KeyVersion> source in keyVersions) { DeleteObjectsRequest request = new DeleteObjectsRequest() { BucketName = AccountInfo.Current.BucketName }; request.Objects = source.ToList(); try { AccountInfo.Current.S3Client.DeleteObjects(request); } catch (DeleteObjectsException) { throw new Exception($"Some of the directory '{path}' underlying objects weren't deleted correctly"); } } this.Provider.DeleteObject(S3ObjectFactory.GetInfo(CMS.IO.Path.EnsureEndBackslash(path))); }
/// <summary> /// Initializes new instance of S3 object info with specified bucket name. /// </summary> /// <param name="path">Path with file name.</param> /// <param name="key">Specifies that given path is already object key.</param> public S3ObjectInfo(string path, bool key) { this.Key = key ? path : PathHelper.GetObjectKeyFromPath(path); if (path == null || !path.EndsWith("\\", StringComparison.Ordinal) || this.Key.EndsWith("/", StringComparison.Ordinal)) { return; } this.Key += "/"; }
/// <summary> /// Determines whether the given path refers to an existing directory on Amazon S3 storage. /// </summary> /// <param name="path">Path to test.</param> public static bool ExistsInS3Storage(string path) { path = PathHelper.GetValidPath(path); string objectKeyFromPath = PathHelper.GetObjectKeyFromPath(path); if (!string.IsNullOrEmpty(objectKeyFromPath)) { return(S3ObjectFactory.Provider.ObjectExists(S3ObjectFactory.GetInfo($"{objectKeyFromPath}/", true))); } return(true); }
/// <summary>Loads metadata from special file from S3 storage.</summary> /// <param name="path">Path.</param> private Dictionary <string, string> LoadMetadata(string path) { string path1 = $"{path}{METADATA_EXT}"; var dictionary = new Dictionary <string, string>(); var s3ObjectInfo = new S3ObjectInfo(path1); GetObjectRequest request = new GetObjectRequest { BucketName = this.BucketName, Key = $"{METADATA_FOLDER}{PathHelper.GetObjectKeyFromPath(path1)}" }; if (path1.StartsWith(Directory.CurrentDirectory, StringComparison.Ordinal)) { path1 = path1.Substring(Directory.CurrentDirectory.Length); } string str1 = Path.Combine(PathHelper.TempPath, $"{METADATA_FOLDER}{path1}"); try { using (GetObjectResponse getObjectResponse = this.S3Client.GetObject(request)) { getObjectResponse.WriteResponseStreamToFile(str1); } } catch (AmazonS3Exception ex) { if (ex.StatusCode == HttpStatusCode.NotFound) { return(dictionary); } } string str2 = System.IO.File.ReadAllText(str1); char[] separator = new char[1] { '#' }; int num = 1; foreach (string str3 in str2.Split(separator, (StringSplitOptions)num)) { char[] chArray = new char[1] { ';' }; string[] strArray = str3.Split(chArray); dictionary.Add(strArray[0], strArray[1]); } return(dictionary); }
/// <summary> /// Returns URL to file. If can be accessed directly then direct URL is generated else URL with GetFile page is generated. /// </summary> /// <param name="path">Virtual path starting with ~ or absolute path.</param> /// <param name="siteName">Site name.</param> public override string GetFileUrl(string path, string siteName) { if (!this.ExistsInS3Storage(path)) { return(null); } string objectKeyFromPath = PathHelper.GetObjectKeyFromPath(path); if (AmazonHelper.PublicAccess) { return($"{AmazonHelper.EndPoint}/{objectKeyFromPath}".ToLowerCSafe()); } string downloadPath = AmazonHelper.GetDownloadPath(objectKeyFromPath); return(this.ResolveUrl(downloadPath)); }
/// <summary>Saves metadata to special file into S3 storage.</summary> /// <param name="path">Path.</param> /// <param name="metadata">Metadata.</param> private void SaveMetadata(string path, Dictionary <string, string> metadata) { string path1 = $"{path}{METADATA_EXT}"; var sb = new StringBuilder(); foreach (var keyValuePair in metadata) { sb.Append($"{keyValuePair.Key};{keyValuePair.Value}#"); } this.S3Client.PutObject(new PutObjectRequest() { BucketName = this.BucketName, ContentBody = sb.ToString(), Key = $"{METADATA_FOLDER}{PathHelper.GetObjectKeyFromPath(path1)}" }); }
/// <summary>Prepares files for import. Converts them to lower case.</summary> /// <param name="path">Path.</param> public override void PrepareFilesForImport(string path) { path = PathHelper.GetValidPath(path); foreach (string objects in this.Provider.GetObjectsList(path, ObjectTypeEnum.FilesAndDirectories, true, false, true)) { IS3ObjectInfo info1 = S3ObjectFactory.GetInfo(PathHelper.GetObjectKeyFromPath(objects, false), true); string lowerInvariant = info1.Key.ToLowerInvariant(); if (lowerInvariant != info1.Key) { IS3ObjectInfo info2 = S3ObjectFactory.GetInfo(info1.Key, true); IS3ObjectInfo info3 = S3ObjectFactory.GetInfo(lowerInvariant, true); this.Provider.CopyObjects(info2, info3); this.Provider.DeleteObject(info2); } } }
/// <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()); }