video : Cómo acceder al Storage de Azure Utilizando REST | WinRT | C#
Avanzado
Esto puede ser muy útil cuando no puedes usar Azure SDK o cuando no hay una versión del SDK disponible para el lenguaje o plataforma que manejas.
El video se hizo en WinRT + C# pero el mecanismo puede ser imitado desde otros lenguajes y frameworks.
En este video también se muestra como construir el header de autorización incluyendo como crear la firma [ signature ] con el Storage Key.
Acá el código fuente
using System;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
namespace App5.Storage
{
public class BlockBlobStorage
{
private const string X_MS_BLOCK_BLOB = "BlockBlob";
private const string X_MS_VERSION = "2012-02-12";
public string Account { get; set; }
public string Key { get; set; }
public BlockBlobStorage(string account, string key)
{
Account = account;
Key = key;
}
public async Task<HttpResponseMessage> UploadAsync(string blobname, Stream stream,
string mimetype = "application/octect-stream")
{
var httpClient = new HttpClient();
var content = new StreamContent(stream);
var tmpdate = RFC1123DateTime;
//headers
content.Headers.ContentType = new MediaTypeHeaderValue(mimetype);
httpClient.DefaultRequestHeaders.Add("x-ms-date", tmpdate);
httpClient.DefaultRequestHeaders.Add("x-ms-blob-type", X_MS_BLOCK_BLOB);
httpClient.DefaultRequestHeaders.Add("x-ms-version", X_MS_VERSION);
string signature = CreateSignature(
HTTPVerb: "PUT",
ContentLength: stream.Length.ToString(),
ContentType: mimetype,
CanonicalizedHeaders: "x-ms-blob-type:BlockBlob\nx-ms-date:" + tmpdate + "\nx-ms-version:2012-02-12",
CanonicalizedResource: string.Format("/{0}/{1}", Account, blobname)
);
httpClient.DefaultRequestHeaders.Add("Authorization",
string.Format("SharedKey {0}:{1}", Account, signature));
return await httpClient.PutAsync(
string.Format("https://{0}.blob.core.windows.net/{1}", Account, blobname),
content
);
}
private string CreateSignature(
string HTTPVerb = "",
string ContentEncoding = "",
string ContentLanguage = "",
string ContentLength = "",
string ContentMD5 = "",
string ContentType = "",
string Date = "",
string IfModifiedSince = "",
string IfMatch = "",
string IfNoneMatch = "",
string IfUnmodifiedSince = "",
string Range = "",
string CanonicalizedHeaders = "",
string CanonicalizedResource = ""
)
{
var sumstring = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}\n{12}\n{13}",
HTTPVerb, ContentEncoding, ContentLanguage, ContentLength, ContentMD5,
ContentType, Date, IfModifiedSince, IfMatch, IfNoneMatch, IfUnmodifiedSince,
Range, CanonicalizedHeaders, CanonicalizedResource
);
return ComputeHMAC_SHA256(sumstring);
}
private string ComputeHMAC_SHA256(string input)
{
var alg = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA256");
//preparar input
var inputBuffer = CryptographicBuffer.ConvertStringToBinary(input, BinaryStringEncoding.Utf8);
//preparar key
var keybuffer = CryptographicBuffer.DecodeFromBase64String(Key);
var hmacKey = alg.CreateKey(keybuffer);
var signbuffer = CryptographicEngine.Sign(hmacKey, inputBuffer);
return CryptographicBuffer.EncodeToBase64String(signbuffer);
}
public string RFC1123DateTime { get { return DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); } }
}
}
Ejemplo de uso
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/chocorramo.jpg"));
var stream = await file.OpenStreamForReadAsync();
var blobUploader = new BlockBlobStorage("jk4freeusage", "Yk4KMu8b0FAzCuqJf4y3j5XSslLxqXYndfkReWg8YkLFVaQOzF1Ga4eAE8jy+rEyOMh9RP228rz0SB2uwkoOoQ==");
var rta = await blobUploader.UploadAsync("imagenes/chocorramo.jpg", stream, mimetype: "image/jpeg");