Skip to content

Instantly share code, notes, and snippets.

@crowcoder
Created June 11, 2015 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crowcoder/de113d8c4ae50a9594e7 to your computer and use it in GitHub Desktop.
Save crowcoder/de113d8c4ae50a9594e7 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
namespace Blobber
{
public class BlobWorker
{
public string ConxnStr { get; set; }
/// <summary>
/// A class with helper methods to perform storage operations.
/// </summary>
/// <param name="cnxn">The connection string to access the storage account. This is the main full access
/// connection string.</param>
public BlobWorker(string cnxn)
{
if (string.IsNullOrWhiteSpace(cnxn))
{
throw new ArgumentNullException("The connection string cannot be null or blank");
}
ConxnStr = cnxn;
}
/// <summary>
/// Gets shared access signature that can be used for performing storage operations on a container.
/// </summary>
/// <param name="containerName">The name of the container to generate the sas token for.</param>
/// <param name="minsToExpiry">The number of minutes the sas token will expire in.</param>
/// <param name="delete">True if you want the consumer of the sas token to be able to delete blobs.</param>
/// <param name="list">True if you want the consumer of the sas token to be able to list blobs in the container</param>
/// <param name="none">True if you want the consumer to have no access. What is this for then????</param>
/// <param name="read">True if you want the consumer to have read access to the container.</param>
/// <param name="write">True if you want the consumer to have write access to the container.</param>
/// <returns></returns>
public string GetContainerSharedAccessSignature(string containerName,
int minsToExpiry, bool delete, bool list, bool none, bool read, bool write)
{
SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
policy.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(minsToExpiry);
if (delete)
policy.Permissions = policy.Permissions | SharedAccessBlobPermissions.Delete;
if (list)
policy.Permissions = policy.Permissions | SharedAccessBlobPermissions.List;
if (none)
policy.Permissions = policy.Permissions | SharedAccessBlobPermissions.None;
if (read)
policy.Permissions = policy.Permissions | SharedAccessBlobPermissions.Read;
if (write)
policy.Permissions = policy.Permissions | SharedAccessBlobPermissions.Write;
CloudBlobContainer container = GetContainer(containerName);
string sasContainerToken = container.GetSharedAccessSignature(policy);
return container.Uri + sasContainerToken;
}
/// <summary>
/// Builds a url to a storage blob. Suitable for the value of an img src property
/// or a file download link.
/// </summary>
/// <param name="containername">The name of the container the blob is in.</param>
/// <param name="blobname">The full name of the blob.</param>
/// <param name="expiresin">Number of minutes to expire the sas token.</param>
/// <returns></returns>
public string GetSrcUrlWithSas(string containername, string blobname, int expiresin)
{
CloudBlobContainer container = GetContainer(containername);
string sastoken = GetBlobSharedAccessSignature(containername, blobname, expiresin);
return container.Uri + "/" + blobname + "/" + sastoken;
}
/// <summary>
/// Gets the shared access signature for a specific blob that expires in 'expiresin' minutes.
/// This returns a read-only signature and it can be used in an img src url to show an
/// image on a web page.
/// </summary>
/// <param name="containerName">The name of the container the blob is in.</param>
/// <param name="blobname">The full path to the blob. </param>
/// <param name="expiresin">Number of minutes the token will expire in.</param>
/// <returns>a string that is a shared access signature token.</returns>
/// <example>
/// <code>
/// <img src="https://[your_account].blob.core.windows.net/[container_name]/[path../file_name]?[the_sas_token]" alt="test" />
/// </code>
/// </example>
public string GetBlobSharedAccessSignature(string containerName, string blobname, int expiresin)
{
CloudBlobContainer container = GetContainer(containerName);
CloudBlockBlob blob = container.GetBlockBlobReference(blobname);
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(expiresin);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
string sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);
return sasBlobToken;
}
/// <summary>
/// Writes/Uploads a blob to the container specified in the sas token.
/// </summary>
/// <param name="filePath">The path to the file you want to write/upload. Its name
/// does not have to be what you name it in the container.
/// </param>
/// <param name="blobname">The 'path' to the blob. In Azure storage there is no physical
/// folder heirarchy, but if you design your blob name to look like a folder structure
/// you can later list blobs based on faux 'paths'. So a blob named 'images/personnel/bob.jpg'
/// would be listed in a container query for everything in 'images/personnel' even though
/// that is not really in a folder. </param>
/// <param name="sas">The stored access signature that gives the permissions to upload.</param>
public void WriteFile(string filePath, string blobname, string sas)
{
if (File.Exists(filePath))
{
byte[] filebuffer = File.ReadAllBytes(filePath);
WriteBytes(filebuffer, blobname, sas);
}
else
{
throw new FileNotFoundException("File : " + filePath + " does not exist");
}
}
/// <summary>
/// Writes/Uploads a blob to the container specified in the sas token.
/// </summary>
/// <param name="blobbytes">The file to upload as a byte array.</param>
/// <param name="blobname">The 'path' to the blob. In Azure storage there is no physical
/// folder heirarchy, but if you design your blob name to look like a folder structure
/// you can later list blobs based on faux 'paths'. So a blob named 'images/personnel/bob.jpg'
/// would be listed in a container query for everything in 'images/personnel' even though
/// that is not really in a folder. </param>
/// <param name="sas">The stored access signature that gives the permissions to upload.</param>
public void WriteBytes(byte[] blobbytes, string blobname, string sas)
{
CloudBlobContainer container = GetContainerFromSas(sas);
CloudBlockBlob blkBlob = container.GetBlockBlobReference(blobname);
blkBlob.UploadFromByteArray(blobbytes, 0, blobbytes.Length);
}
/// <summary>
/// Returns a CloudBlobContainer reference built with a storage access token. The blob URI is
/// restricted to the permissions of the sas token.
/// </summary>
/// <param name="containerSas"></param>
/// <returns></returns>
private CloudBlobContainer GetContainerFromSas(string containerSas)
{
try
{
CloudBlobContainer theContainer = new CloudBlobContainer(new Uri(containerSas));
return theContainer;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Returns a CloudBlobContainer reference that is not restricted by a sas token.
/// </summary>
/// <param name="containername"></param>
/// <returns></returns>
private CloudBlobContainer GetContainer(string containername)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConxnStr);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containername);
container.CreateIfNotExists();
return container;
}
/// <summary>
/// Gets a CloudStorageAccount reference based on the connection string.
/// </summary>
/// <returns>CloudStorageAccount</returns>
/// <exception cref="System.ArgumentNullException">Connection string cannot be null</exception>
/// <exception cref="System.FormatException">Connection string format is incorrect</exception>
/// <exception cref="System.ArgumentException">Connection string is invalid</exception>
private CloudStorageAccount GetStorageAcct()
{
return CloudStorageAccount.Parse(ConxnStr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment