Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 93 additions & 32 deletions BlobStorage/Advanced.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public static class Advanced
// Prefix for containers created by the sample.
private const string ContainerPrefix = "sample-";

// Variable for saving the user's service property settings.
private static ServiceProperties properties = null;
// Prefix for blob created by the sample.
private const string BlobPrefix = "sample-blob-";

/// <summary>
/// Calls the advanced samples for Blob storage.
Expand All @@ -62,7 +62,7 @@ public static async Task CallBlobAdvancedSamples()
userServiceProperties = await blobClient.GetServicePropertiesAsync();

// Get a reference to a sample container.
container = CreateSampleContainer(blobClient).Result;
container = await CreateSampleContainer(blobClient);

// Call Blob service client samples.
await CallBlobClientSamples(blobClient);
Expand Down Expand Up @@ -162,14 +162,20 @@ private static async Task CallContainerSamples(CloudBlobContainer container)
await ManageContainerLeases(container.ServiceClient);
}


/// <summary>
/// Calls samples that demonstrate how to work with blobs.
/// </summary>
/// <param name="container">A CloudBlobContainer object.</param>
/// <returns>A Task object.</returns>
private static async Task CallBlobSamples(CloudBlobContainer container)
{
// Create a blob with a random name.
CloudBlockBlob blob = await CreateRandomlyNamedBlockBlob(container);

// Get a reference to the blob created above from the server.
// This call will fail if the blob does not yet exist.
await GetExistingBlobReference(container, blob.Name);

// Create a specified number of block blobs in a flat structure.
await CreateSequentiallyNamedBlockBlobs(container, 5);

Expand All @@ -194,7 +200,6 @@ private static async Task CallBlobSamples(CloudBlobContainer container)
await UploadBlobInBlocks(container);
}


/// <summary>
/// Calls shared access signature samples for both containers and blobs.
/// </summary>
Expand Down Expand Up @@ -296,7 +301,6 @@ private static async Task ConfigureBlobAnalytics(CloudBlobClient blobClient)
}
}


/// <summary>
/// Gets the Blob service stats for the secondary endpoint for an RA-GRS (read-access geo-redundant) storage account.
/// </summary>
Expand Down Expand Up @@ -430,7 +434,7 @@ private static async Task ListContainersWithPrefix(CloudBlobClient blobClient, s
private static async Task<CloudBlobContainer> CreateSampleContainer(CloudBlobClient blobClient)
{
// Name sample container based on new GUID, to ensure uniqueness.
string containerName = ContainerPrefix + Guid.NewGuid().ToString();
string containerName = ContainerPrefix + Guid.NewGuid();

// Get a reference to a sample container.
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
Expand All @@ -452,7 +456,6 @@ private static async Task<CloudBlobContainer> CreateSampleContainer(CloudBlobCli
return container;
}


/// <summary>
/// Add some sample metadata to the container.
/// </summary>
Expand All @@ -477,7 +480,6 @@ private static async Task AddContainerMetadata(CloudBlobContainer container)
}
}


/// <summary>
/// Sets the anonymous access level.
/// </summary>
Expand Down Expand Up @@ -506,7 +508,6 @@ private static async Task SetAnonymousAccessLevel(CloudBlobContainer container,
throw;
}
}


/// <summary>
/// Reads the container's properties.
Expand All @@ -532,7 +533,6 @@ private static void PrintContainerPropertiesAndMetadata(CloudBlobContainer conta
Console.WriteLine();
}


/// <summary>
/// Demonstrates container lease states: available, breaking, broken, and expired.
/// A lease is used in each example to delete the container.
Expand Down Expand Up @@ -562,7 +562,7 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
*/

// Lease is available on the new container. Acquire the lease and delete the leased container.
container1 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid().ToString());
container1 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container1.CreateIfNotExistsAsync();

// Get container properties to see the available lease.
Expand All @@ -585,7 +585,7 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
Case 2: Lease is breaking
*/

container2 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid().ToString());
container2 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container2.CreateIfNotExistsAsync();

// Acquire the lease.
Expand All @@ -609,7 +609,7 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
Case 3: Lease is broken
*/

container3 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid().ToString());
container3 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container3.CreateIfNotExistsAsync();

// Acquire the lease.
Expand All @@ -630,7 +630,7 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
Case 4: Lease has expired.
*/

container4 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid().ToString());
container4 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container4.CreateIfNotExistsAsync();

// Acquire the lease.
Expand All @@ -651,7 +651,7 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
Case 5: Attempt to delete leased container without lease ID.
*/

container5 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid().ToString());
container5 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container5.CreateIfNotExistsAsync();

// Acquire the lease.
Expand Down Expand Up @@ -698,7 +698,6 @@ private static async Task ManageContainerLeases(CloudBlobClient blobClient)
}
}


/// <summary>
/// Reads the lease properties for the container.
/// </summary>
Expand Down Expand Up @@ -756,7 +755,6 @@ private static async Task DeleteContainersWithPrefix(CloudBlobClient blobClient,
}
}


/// <summary>
/// Creates a shared access policy on the container.
/// </summary>
Expand All @@ -769,6 +767,8 @@ private static async Task CreateSharedAccessPolicy(CloudBlobContainer container,
// The access policy provides create, write, read, list, and delete permissions.
SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Delete
Expand All @@ -782,7 +782,6 @@ private static async Task CreateSharedAccessPolicy(CloudBlobContainer container,
await container.SetPermissionsAsync(permissions);
}


/// <summary>
/// Returns a URI containing a SAS for the blob container.
/// </summary>
Expand All @@ -800,7 +799,8 @@ private static string GetContainerSasUri(CloudBlobContainer container, string st
// to construct a shared access policy that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocPolicy = new SharedAccessBlobPolicy()
{
// Omit SAS start time to avoid clock skew. Start time is assumed to be the time when the service receives the request.
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
};
Expand All @@ -826,7 +826,6 @@ private static string GetContainerSasUri(CloudBlobContainer container, string st
return container.Uri + sasContainerToken;
}


/// <summary>
/// Tests a container SAS to determine which operations it allows.
/// </summary>
Expand Down Expand Up @@ -968,7 +967,6 @@ private static async Task TestContainerSAS(string sasUri, string blobName, strin

#endregion


#region AllBlobTypeSamples

/// <summary>
Expand Down Expand Up @@ -1046,7 +1044,6 @@ private static void PrintBlobPropertiesAndMetadata(CloudBlob blob)
Console.WriteLine();
}


/// <summary>
/// Reads the virtual directory's properties.
/// </summary>
Expand Down Expand Up @@ -1125,7 +1122,6 @@ private static async Task ListBlobsFlatListing(CloudBlobContainer container, int
}
}


/// <summary>
/// Lists blobs in the specified container using a hierarchical listing, and calls this method recursively to return the contents of each
/// virtual directory. Reads the properties on each blob or virtual directory returned and writes them to the console window.
Expand Down Expand Up @@ -1189,9 +1185,78 @@ private static async Task ListBlobsHierarchicalListing(CloudBlobContainer contai

#endregion


#region BlockBlobSamples

/// <summary>
/// Creates a randomly named block blob.
/// </summary>
/// <param name="container">The container.</param>
/// <returns>A Task object.</returns>
private static async Task<CloudBlockBlob> CreateRandomlyNamedBlockBlob(CloudBlobContainer container)
{
// Get a reference to a blob that does not yet exist.
// The GetBlockBlobReference method does not make a request to the service, but only creates the object in memory.
string blobName = BlobPrefix + Guid.NewGuid();
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);

// For the purposes of the sample, check to see whether the blob exists.
Console.WriteLine("Blob {0} exists? {1}", blobName, await blob.ExistsAsync());

try
{
// Writing to the blob creates it on the service.
await blob.UploadTextAsync(string.Format("This is a blob named {0}", blobName));
}
catch (StorageException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}

// Check again to see whether the blob exists.
Console.WriteLine("Blob {0} exists? {1}", blobName, await blob.ExistsAsync());

return blob;
}

/// <summary>
/// Gets a reference to a blob by making a request to the service.
/// </summary>
/// <param name="container">The container.</param>
/// <param name="blobName">The blob name.</param>
/// <returns>A Task object.</returns>
private static async Task GetExistingBlobReference(CloudBlobContainer container, string blobName)
{
try
{
// Get a reference to a blob with a request to the server.
// If the blob does not exist, this call will fail with a 404 (Not Found).
ICloudBlob blob = await container.GetBlobReferenceFromServerAsync(blobName);

// The previous call gets the blob's properties, so it's not necessary to call FetchAttributes
// to read a property.
Console.WriteLine("Blob {0} was last modified at {1} local time.", blobName,
blob.Properties.LastModified.Value.LocalDateTime);
}
catch (StorageException e)
{
if (e.RequestInformation.HttpStatusCode == 404)
{
Console.WriteLine("Blob {0} does not exist.", blobName);
Console.WriteLine("Additional error information: " + e.Message);
}
else
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
}

Console.WriteLine();
}

/// <summary>
/// Creates the specified number of sequentially named block blobs, in a flat structure.
/// </summary>
Expand Down Expand Up @@ -1239,7 +1304,6 @@ private static async Task CreateSequentiallyNamedBlockBlobs(CloudBlobContainer c
}
}


/// <summary>
/// Creates the specified number of nested block blobs at a specified number of levels.
/// </summary>
Expand Down Expand Up @@ -1296,7 +1360,6 @@ private static async Task CreateNestedBlockBlobs(CloudBlobContainer container, s
}
}


/// <summary>
/// Gets a reference to a blob created previously, and copies it to a new blob in the same container.
/// </summary>
Expand Down Expand Up @@ -1465,7 +1528,7 @@ private static async Task UploadBlobInBlocks(CloudBlobContainer container)
rnd.NextBytes(randomBytes);

// Get a reference to a new block blob.
CloudBlockBlob blob = container.GetBlockBlobReference("sample-blob-" + Guid.NewGuid().ToString());
CloudBlockBlob blob = container.GetBlockBlobReference("sample-blob-" + Guid.NewGuid());

// Specify the block size as 256 KB.
int blockSize = 256 * 1024;
Expand Down Expand Up @@ -1551,7 +1614,6 @@ private static async Task UploadBlobInBlocks(CloudBlobContainer container)
}
}


/// <summary>
/// Reads the blob's block list, and indicates whether the blob has been committed.
/// </summary>
Expand Down Expand Up @@ -1581,7 +1643,6 @@ private static async Task ReadBlockList(CloudBlockBlob blob)
Console.WriteLine();
}


/// <summary>
/// Returns a URI containing a SAS for the blob.
/// </summary>
Expand All @@ -1604,7 +1665,8 @@ private static string GetBlobSasUri(CloudBlobContainer container, string blobNam
// to construct a shared access policy that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// Omit SAS start time to avoid clock skew. Start time is assumed to be the time when the service receives the request.
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create
};
Expand All @@ -1629,7 +1691,6 @@ private static string GetBlobSasUri(CloudBlobContainer container, string blobNam
return blob.Uri + sasBlobToken;
}


/// <summary>
/// Tests a blob SAS to determine which operations it allows.
/// </summary>
Expand Down
Loading