Skip to content

Instantly share code, notes, and snippets.

@crowcoder
Created June 11, 2014 11:21
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/2d013b44fe6ea0c397c9 to your computer and use it in GitHub Desktop.
Save crowcoder/2d013b44fe6ea0c397c9 to your computer and use it in GitHub Desktop.
Azure Blob Storage Operations
using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace Blobber
{
public class BlobWorker
{
private string _AcctName;
private string _AcctKey;
/// <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 accname, string acctkey)
{
if (string.IsNullOrWhiteSpace(accname))
{
throw new ArgumentNullException("The Account Name cannot be null or blank");
}
if (string.IsNullOrWhiteSpace(acctkey))
{
throw new ArgumentNullException("The Account Key cannot be null or blank");
}
_AcctKey = acctkey;
_AcctName = accname;
}
/// <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;
}
public List<string> GetSrcUrlWithSasByTagNbr(string containername, string dirpath)
{
List<string> theUrls = new List<string>();
CloudBlobClient blobclnt = GetStorageAcct().CreateCloudBlobClient();
CloudBlobContainer cnt = blobclnt.GetContainerReference(containername);
foreach (IListBlobItem item in cnt.ListBlobs(dirpath, true).ToList())
{
CloudBlockBlob cbb = item as CloudBlockBlob;
string blobname = cbb.Name;
string src = GetSrcUrlWithSas(cnt.Name, blobname, 10);
theUrls.Add(src);
}
return theUrls;
}
/// <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.AddDays(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>
/// Draws text on a blob image.
/// </summary>
/// <param name="filestr"></param>
/// <param name="containername"></param>
/// <param name="blobname"></param>
/// <param name="shipperinfo"></param>
public void WriteStream(Stream filestr, string containername, string blobname, string shipperinfo)
{
using (Image img = Bitmap.FromStream(filestr))
{
using (Graphics g = Graphics.FromImage(img))
{
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
g.FillRectangle(Brushes.Black, 0, img.Height - 40, img.Width, 40);
SizeF strsize = g.MeasureString(DateTime.Now.ToString() + " " + shipperinfo, new Font("Consolas", 11));
if (strsize.Width > img.Width - 10)
{
using (Image box = new Bitmap(Convert.ToInt32(strsize.Width + 1), 45))
{
using (Graphics boxgraphics = Graphics.FromImage(box))
{
boxgraphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
boxgraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
boxgraphics.FillRectangle(Brushes.Black, 0, 0, box.Width, box.Height);
boxgraphics.DrawString(
DateTime.Now.ToString() + " " + shipperinfo,
new Font("Consolas", 11),
Brushes.White,
new RectangleF(0f,0f,(float)box.Width, (float)box.Height));
// boxgraphics.ScaleTransform(img.Width - 2f / strsize.Width, 1f);
boxgraphics.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);
g.DrawImage(box, new Point(0, img.Height - 30));
}
}
}
else
{
g.DrawString(DateTime.Now.ToString() + " " + shipperinfo, new Font("Consolas", 11), Brushes.White, new PointF(10, img.Height - 20));
}
g.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);
}
CloudBlobClient cbc = GetStorageAcct().CreateCloudBlobClient();
CloudBlobContainer cbcont = cbc.GetContainerReference(containername);
CloudBlockBlob cbb = cbcont.GetBlockBlobReference(blobname);
Stream s = new MemoryStream();
img.Save(s, ImageFormat.Png);
s.Position = 0;
cbb.UploadFromStream(s);
s.Close();
s.Dispose();
}
}
/// <summary>
/// Returns a list of strings that are anchor links for blobs in a container.
/// </summary>
/// <param name="container"></param>
/// <param name="prefix"></param>
/// <returns></returns>
public List<string> ListBlobsinContainer(string container, string prefix)
{
string earl = "<a href=\"{0}\" target=\"_blank\" ><img height=\"75\" width=\"133\" src=\"{0}\" alt=\"{1}\" /></a>";
List<string> theblobs = new List<string>();
CloudBlobClient blobclnt = GetStorageAcct().CreateCloudBlobClient();
CloudBlobContainer cnt = blobclnt.GetContainerReference(container);
foreach (IListBlobItem item in cnt.ListBlobs(prefix, true))
{
CloudBlockBlob cbb = (CloudBlockBlob)item;
string thename = cbb.Name;
string[] nametokens = cbb.Name.Split(new string[] { "/" },StringSplitOptions.None);
theblobs.Add(string.Format(earl, GetSrcUrlWithSas(container, cbb.Name, 1000), nametokens[nametokens.Length -1]));
}
return theblobs;
}
/// <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 Microsoft.WindowsAzure.Storage.Blob.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 Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer GetContainer(string containername)
{
CloudStorageAccount storageAccount = GetStorageAcct();
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()
{
StorageCredentials creds = new StorageCredentials(_AcctName, _AcctKey);
return new CloudStorageAccount(creds, true);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment