/// <summary> /// Lists the objects in folder. The asset key or name should be the folder. /// If Asset.Key is not provided then one is created using the RootFolder and Asset.Name /// If Key and Name are not provided then list all objects in the current RootFolder. /// If a key is provided it MUST use the full path, RootFolder and Name are not used. /// The last segment in key is the folder name. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset">The asset.</param> /// <returns></returns> public override List <Asset> ListObjectsInFolder(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); var assets = new List <Asset>(); string physicalFolder = FileSystemComponentHttpContext.Server.MapPath(asset.Key); assets.AddRange(GetListOfObjects(assetStorageProvider, physicalFolder, SearchOption.TopDirectoryOnly, AssetType.Folder)); assets.AddRange(GetListOfObjects(assetStorageProvider, physicalFolder, SearchOption.TopDirectoryOnly, AssetType.File)); return(assets.OrderBy(a => a.Key).ToList()); }
/// <summary> /// Creates the download link. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset">The asset.</param> /// <returns></returns> public override string CreateDownloadLink(AssetStorageProvider assetStorageProvider, Asset asset) { try { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); string domainName = FileSystemComponentHttpContext.Request.UrlProxySafe().GetLeftPart(UriPartial.Authority); string uriKey = asset.Key.TrimStart('~'); return(domainName + uriKey); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Gets the object as an Asset and creates the thumbnail. /// </summary> /// <param name="assetStorageProvider">The asset storage provider.</param> /// <param name="asset">The asset.</param> /// <returns></returns> public override Asset GetObject(AssetStorageProvider assetStorageProvider, Asset asset) { return(GetObject(assetStorageProvider, asset, true)); }
/// <summary> /// Lists the folder in folder. Asset.Key or Asset.Name is the folder. /// If Asset.Key is not provided then one is created using the RootFolder and Asset.Name. /// If Key and Name are not provided the list then list all files in the current RootFolder. /// If a key is provided it MUST use the full path, RootFolder and Name are not used. /// The last segment in the key is the folder name. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset">The asset.</param> /// <returns></returns> public override List <Asset> ListFoldersInFolder(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); string physicalFolder = FileSystemComponentHttpContext.Server.MapPath(asset.Key); var assets = new List <Asset>(); if (!HiddenFolders.Any(a => physicalFolder.IndexOf(a, StringComparison.OrdinalIgnoreCase) > 0)) { assets = GetListOfObjects(assetStorageProvider, physicalFolder, SearchOption.TopDirectoryOnly, AssetType.Folder); } return(assets); }
/// <summary> /// Deletes the image thumbnail for the provided Asset. If the asset is a file then the singel thumbnail /// is deleted. If the asset is a directory then a recurrsive delete is done. /// </summary> /// <param name="assetStorageProvider">The asset storage provider.</param> /// <param name="asset">The asset.</param> protected override void DeleteImageThumbnail(AssetStorageProvider assetStorageProvider, Asset asset) { base.DeleteImageThumbnail(assetStorageProvider, asset); }
/// <summary> /// Deletes all of the S3Objects in the provided folder asset. /// </summary> /// <param name="client">The client.</param> /// <param name="assetStorageProvider">The asset storage Provider.</param> /// <param name="asset">The asset.</param> /// <returns></returns> private bool MultipleObjectDelete(AmazonS3Client client, AssetStorageProvider assetStorageProvider, Asset asset) { // The list of keys that will be passed into the multiple delete request List <KeyVersion> keys = new List <KeyVersion>(); // Amazon only accepts 1000 keys per request, use this to keep track of how many already sent int keyIndex = 0; try { // Get a list of objest with prefix var assetDeleteList = ListObjects(assetStorageProvider, asset); // Create the list of keys foreach (var assetDelete in assetDeleteList) { keys.Add(new KeyVersion { Key = assetDelete.Key }); } while (keyIndex < keys.Count()) { int range = keys.Count() - keyIndex < 1000 ? keys.Count() - keyIndex : 1000; var deleteObjectsRequest = new DeleteObjectsRequest { BucketName = GetAttributeValue(assetStorageProvider, "Bucket"), Objects = keys.GetRange(keyIndex, range) }; DeleteObjectsResponse response = client.DeleteObjects(deleteObjectsRequest); keyIndex += range; } return(true); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Gets the objects in folder without recursion. i.e. will get the list of files /// and folders in the folder but not the contents of the subfolders. Subfolders /// will not have the ModifiedDate prop filled in as Amazon doesn't provide it in /// this context. /// </summary> /// <param name="assetStorageProvider">The asset storage Provider.</param> /// <param name="asset">The asset.</param> /// <returns></returns> public override List <Asset> ListObjectsInFolder(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); string bucketName = GetAttributeValue(assetStorageProvider, "Bucket"); asset.Key = FixKey(asset, rootFolder); HasRequirementsFolder(asset); try { AmazonS3Client client = GetAmazonS3Client(assetStorageProvider); ListObjectsV2Request request = new ListObjectsV2Request(); request.BucketName = bucketName; request.Prefix = asset.Key == "/" ? rootFolder : asset.Key; request.Delimiter = "/"; var assets = new List <Asset>(); var subFolders = new HashSet <string>(); ListObjectsV2Response response; // S3 will only return 1,000 keys per response and sets IsTruncated = true, the do-while loop will run and fetch keys until IsTruncated = false. do { response = client.ListObjectsV2(request); foreach (S3Object s3Object in response.S3Objects) { if (s3Object.Key == null) { continue; } var responseAsset = CreateAssetFromS3Object(assetStorageProvider, s3Object, client.Config.RegionEndpoint.SystemName); assets.Add(responseAsset); } // After setting the delimiter S3 will filter out any prefixes below that in response.S3Objects. // So we need to inspect response.CommonPrefixes to get the prefixes inside the folder. foreach (string subFolder in response.CommonPrefixes) { if (subFolder.IsNotNullOrWhiteSpace()) { subFolders.Add(subFolder); } } request.ContinuationToken = response.NextContinuationToken; } while (response.IsTruncated); // Add the subfolders to the asset collection foreach (string subFolder in subFolders) { var subFolderAsset = CreateAssetFromCommonPrefix(subFolder, client.Config.RegionEndpoint.SystemName, bucketName); assets.Add(subFolderAsset); } return(assets.OrderBy(a => a.Key, StringComparer.OrdinalIgnoreCase).ToList()); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Creates the download link. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset">The asset.</param> /// <returns></returns> public override string CreateDownloadLink(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); try { AmazonS3Client client = GetAmazonS3Client(assetStorageProvider); GetPreSignedUrlRequest request = new GetPreSignedUrlRequest { BucketName = GetAttributeValue(assetStorageProvider, "Bucket"), Key = asset.Key, Expires = DateTime.Now.AddMinutes(GetAttributeValue(assetStorageProvider, "Expiration").AsDouble()) }; return(client.GetPreSignedURL(request)); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Lists the folder in folder. Asset.Key or Asset.Name is the folder. /// If Asset.Key is not provided then one is created using the RootFolder and Asset.Name. /// If Key and Name are not provided the list then list all files in the current RootFolder. /// If a key is provided it MUST use the full path, RootFolder and Name are not used. /// The last segment in the key is the folder name. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset">The asset.</param> /// <returns></returns> public override List <Asset> ListFoldersInFolder(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); string bucketName = GetAttributeValue(assetStorageProvider, "Bucket"); asset.Key = FixKey(asset, rootFolder); HasRequirementsFolder(asset); try { AmazonS3Client client = GetAmazonS3Client(assetStorageProvider); ListObjectsV2Request request = new ListObjectsV2Request(); request.BucketName = bucketName; request.Prefix = asset.Key == "/" ? string.Empty : asset.Key; request.Delimiter = "/"; var assets = new List <Asset>(); // All "folders" will be in the CommonPrefixes property. There is no need to loop through truncated responses like there is for files. ListObjectsV2Response response = client.ListObjectsV2(request); foreach (string subFolder in response.CommonPrefixes) { if (subFolder.IsNotNullOrWhiteSpace()) { var subFolderAsset = CreateAssetFromCommonPrefix(subFolder, client.Config.RegionEndpoint.SystemName, bucketName); assets.Add(subFolderAsset); } } return(assets.OrderBy(a => a.Key, StringComparer.OrdinalIgnoreCase).ToList()); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Lists the files in folder. Asset.Key or Asset.Name is the folder. /// If Asset.Key is not provided then one is created using the RootFolder and Asset.Name. /// If Key and Name are not provided then list all files in the current RootFolder. /// If a key is provided it MUST use the full path, RootFolder and Name are not used. /// The last segment in the key is the folder name. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset"></param> /// <returns></returns> public override List <Asset> ListFilesInFolder(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); HasRequirementsFolder(asset); try { AmazonS3Client client = GetAmazonS3Client(assetStorageProvider); ListObjectsV2Request request = new ListObjectsV2Request(); request.BucketName = GetAttributeValue(assetStorageProvider, "Bucket"); request.Prefix = asset.Key == "/" ? string.Empty : asset.Key; request.Delimiter = "/"; var assets = new List <Asset>(); ListObjectsV2Response response; // S3 will only return 1,000 keys per response and sets IsTruncated = true, the do-while loop will run and fetch keys until IsTruncated = false. do { response = client.ListObjectsV2(request); foreach (S3Object s3Object in response.S3Objects) { if (s3Object.Key == null || s3Object.Key.EndsWith("/")) { continue; } var responseAsset = CreateAssetFromS3Object(assetStorageProvider, s3Object, client.Config.RegionEndpoint.SystemName); assets.Add(responseAsset); } request.ContinuationToken = response.NextContinuationToken; } while (response.IsTruncated); return(assets.OrderBy(a => a.Key, StringComparer.OrdinalIgnoreCase).ToList()); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }
/// <summary> /// Lists the objects. If Asset.Key is not provided then one is created using the RootFolder and Asset.Name. /// If key and name are not provided then list all objects from the current RootFolder. /// If a key is provided it MUST use the full path, RootFolder is not used, and Name is not used. /// The last segment in Key is treated as a begins with search if it does not end in a '/'. e.g. to get all /// files starting with 'mr' in folder 'pictures/cats/' set key = 'pictures/cats/mr' to get 'mr. whiskers' /// and 'mrs. whiskers' but not 'fluffy' or 'carnage the attack cat'. /// </summary> /// <param name="assetStorageProvider"></param> /// <param name="asset"></param> /// <returns></returns> public override List <Asset> ListObjects(AssetStorageProvider assetStorageProvider, Asset asset) { string rootFolder = FixRootFolder(GetAttributeValue(assetStorageProvider, "RootFolder")); asset.Key = FixKey(asset, rootFolder); try { AmazonS3Client client = GetAmazonS3Client(assetStorageProvider); ListObjectsV2Request request = new ListObjectsV2Request(); request.BucketName = GetAttributeValue(assetStorageProvider, "Bucket"); request.Prefix = asset.Key == "/" ? GetAttributeValue(assetStorageProvider, "RootFolder") : asset.Key; var assets = new List <Asset>(); ListObjectsV2Response response; do { response = client.ListObjectsV2(request); foreach (S3Object s3Object in response.S3Objects) { if (s3Object.Key == null) { continue; } var responseAsset = CreateAssetFromS3Object(assetStorageProvider, s3Object, client.Config.RegionEndpoint.SystemName); assets.Add(responseAsset); } request.ContinuationToken = response.NextContinuationToken; } while (response.IsTruncated); return(assets.OrderBy(a => a.Key, StringComparer.OrdinalIgnoreCase).ToList()); } catch (Exception ex) { ExceptionLogService.LogException(ex); throw; } }