Visual Studio 2008
¿Cómo agregamos referencias web entonces?
Add-PSSnapin AzureManagementToolsSnapIn
Get-Command -PSSnapIn AzureManagementToolsSnapIn
New-Deployment -serviceName <LOWER_CASE_SERVICENAME> -storageServiceName <LOWER_CASE_STORAGE_SERVICE_NAME> -subscriptionId <YOUR_SUBSCRIPTION_ID> -certificate (get-item cert:CurrentUserMY<CERTIFICATE_THUMPRINT>) -slot staging –package <PACKAGE_LOCATION> -configuration <CONFIGURATION_LOCATION> -label "From PS"
New-Deployment -serviceName returngis -storageServiceName myazurestorage -subscriptionId 5rtegtsw-0i93d-46b0-5tre-nh64w24 -certificate (get-item cert:CurrentUserMY327BBBABFE909FDJGR9ERJGFGDDFS30E76D370F2F95) -slot staging –package c:DeployWindowsAzurePowerShell.cspkg -configuration C:DeployServiceConfiguration.cscfg -label "From PS"
Set-DeploymentStatus -status running -slot <staging/production> -serviceName <LOWER_CASE_SERVICENAME> -SubscriptionId <YOUR_SUBSCRIPTION_ID> -certificate (get-item cert:CurrentUserMY<CERTIFICATE_THUMPRINT>)
Set-DeploymentStatus -status running -slot staging -serviceName returngis -SubscriptionId 5rtegtsw-0i93d-46b0-5tre-nh64w24 -certificate (get-item cert:CurrentUserMY327BBBABFE909FDJGR9ERJGFGDDFS30E76D370F2F95)
Remove-deployment -slot staging -serviceName <LOWER_CASE_SERVICENAME> -subscriptionId <YOUR_SUBSCRIPTION_ID> -certificate (get-item cert:CurrentUserMY<CERTIFICATE_THUMPRINT>)
Set-DeploymentStatus -status suspended -slot <staging/production> -serviceName <LOWER_CASE_SERVICENAME> -SubscriptionId <YOUR_SUBSCRIPTION_ID> -certificate (get-item cert:CurrentUserMY<CERTIFICATE_THUMPRINT>)
Set-DeploymentStatus -status running -slot staging -serviceName <LOWER_CASE_STORAGE_SERVICE_NAME> -SubscriptionId <YOUR_SUBSCRIPTION_ID> -certificate (get-item cert:CurrentUserMY<CERTIFICATE_THUMPRINT>) | Get-OperationStatus -WaitToComplete
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; namespace CheckerWindowsService { public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { } protected override void OnStop() { } } }
protected override void OnStart(string[] args) { var timer = new Timer { AutoReset = true, Interval = 60000 }; timer.Elapsed += timer_Elapsed; timer.Start(); } private void timer_Elapsed(object sender, ElapsedEventArgs e) { var processes = Process.GetProcessesByName("firefox"); foreach (var process in processes) { process.CloseMainWindow(); if (!process.HasExited) { process.Kill(); process.Close(); } } }
InstallUtil.exe miEjecutable.exe
InstallUtil.exe /u miEjecutable.exe
blob.Delete(new BlobRequestOptions() { DeleteSnapshotsOption = DeleteSnapshotsOption.IncludeSnapshots });
blob.GetBlobReference("filename?snapshot=<DateTime>");
<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName, item.SnapShotTime})%>
<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName, item.SnapShotTime.Ticks })%>
public void DeleteBlob(string uri, string containerName, long snapShotTimeTicks) { var container = GetContainer(containerName); CloudBlob blob; if (snapShotTimeTicks != 0) { var utcSnapshotTime = new DateTime(snapShotTimeTicks, DateTimeKind.Utc); blob = _blobClient.GetBlobReference(uri, utcSnapshotTime); } else blob = container.GetBlobReference(uri); blob.Delete(); }
Hace bastante tiempo escribí un post donde explicaba cómo era posible la creación de un archivo Excel con Open XML utilizando una base de datos como fuente. Esta vez, voy a comentar cómo podemos leer datos de una hoja para poder manipularlos desde C#.
Antes de comenzar, necesitamos utilizar las referencias Windows Base y DocumentFormat.OpenXml. En este ejemplo, vamos a recuperar los siguientes valores:
La información más importante de este archivo para poder recuperar correctamente los datos son el nombre de la hoja y el número de la fila donde comienzan los datos que nos interesan.
El objetivo de nuestro código será recuperar estos datos y almacenarlos en un txt de forma formateada. Creamos un proyecto de consola y comenzamos con el siguiente código:
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;namespace ExcelOpenXML
{
class Program
{
static void Main()
{using (var document = SpreadsheetDocument.Open(@»C:BooksSample.xlsx», true))
{var workbook = document.WorkbookPart.Workbook;
var workSheets = workbook.Descendants<Sheet>();string sheetId = workSheets.First(s => s.Name == @»Hoja1″).Id;
var sheet = (WorksheetPart)document.WorkbookPart.GetPartById(sheetId);var sharedStringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
var books = Library.RetrieveBooks(sheet.Worksheet, sharedStringTable);
using (var sw = new StreamWriter(@»c:Books.txt»))
{
foreach (var p in from book in books select book)
sw.WriteLine(«{0, -40} {1, -20} «, p.Name, p.Price);
}}
}
}
}
Si nos fijamos en el código anterior, una vez cargado el archivo tenemos que acceder al objeto workbook, solicitamos todas las hojas en orden descendente y recuperamos el id de aquella que tenga como nombre Hoja1. Con este id podemos recuperar la hoja en cuestión y, por otro lado, recuperamos un elemento llamado SharedStringTable, el cual contiene un conjunto de elementos donde están alojadas todas las cadenas utilizadas en la hoja. Para que os hagáis una idea de lo que estamos recuperando, podemos abrir el archivo con Open XML SDK 2.0 Productivity Tool for Microsoft Office y visualizar su esquema:
¿Cómo recuperamos la información entre tanto XML?
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using DocumentFormat.OpenXml.Spreadsheet;namespace ExcelOpenXML
{
public class Library
{
static readonly CultureInfo Culture = new CultureInfo(«en-US»);public static List<Book> RetrieveBooks(Worksheet worksheet, SharedStringTable sharedStringTable)
{
var result = new List<Book>();var dataRows = from row in worksheet.Descendants<Row>()
where row.RowIndex > 6 //The table begins on line 5
select row;foreach (var row in dataRows)
{
var textValues = new List<string>();
foreach (var cell in from cell in row.Descendants<Cell>() where cell.CellValue != null select cell)
{
if (cell.DataType != null && cell.DataType.HasValue && cell.DataType == CellValues.SharedString)
textValues.Add(sharedStringTable.ChildElements[int.Parse(cell.CellValue.InnerText)].InnerText);
else
textValues.Add(cell.CellValue.InnerText);
}var textArray = textValues.ToArray();
if (textArray.Count() <= 0) continue;
var book = new Book
{
Name = textArray[0],
Price = textArray[1] == «?» ? 0 : float.Parse(textArray[1], NumberStyles.Float, Culture),
};result.Add(book);
}return result;
}
}
}
Aunque la tabla comience en la fila 5, realmente nos interesa recuperar solamente los datos y obviar la cabecera. Una vez recuperados todos los registros, recorremos cada uno de ellos para poder almacenar la información en el objeto Book, el cual sólo contiene dos propiedades: Name y Price.
Un dato importante es utilizar la cultura en-US ya que, al recuperar los valores del archivo, el SDK de Open XML recupera los valores con punto en vez de coma. Este sería el resultado con el parseo pero sin la cultura en-US.
Introducing HTML5 (Voices That Matter) 1,756E+16
JavaScript: The Good Parts 1383
CSS: The Missing Manual 1,756E+16
JavaScript: The Definitive Guide 2371
Programming in Objective-C 2.0 2223
Si ejecutamos la aplicación, abrirá el archivo xlsx y, una vez cargados en memoria, escribirá uno a uno en el archivo Books.txt. El resultado sería el siguiente:
Introducing HTML5 (Voices That Matter) 17,56
JavaScript: The Good Parts 13,83
CSS: The Missing Manual 17,56
JavaScript: The Definitive Guide 23,71
Programming in Objective-C 2.0 22,23
Adjunto el proyecto por si fuera de utilidad
¡Saludos!
Hace un par de días me dieron la oportunidad de participar en la beta de Windows Azure Connect . Para quien no haya oído hablar de este futuro servicio, Windows Azure Connect nos dará la posibilidad de conectar servidores on-premise con nuestros roles ubicados en la nube, lo que se conoce como VPN .
En este post voy a hacer una demo muy sencilla de cómo configurar este servicio y comprobar la conectividad entre dos máquinas a través de un ping.
Accedemos al portal y nos posicionamos en el apartado Virtual Network.
Si es la primera vez que accedemos, deberemos activar la suscripción para Azure Connect.
Con la suscripción seleccionada, pulsamos en el botón Get Activation Token, el cual nos devolverá un token que deberemos utilizar para que nuestro role en la nube pueda formar parte de un grupo que veremos más adelante.
Para realizar esta demo, crearemos un nuevo proyecto Windows Azure Project con un web role con el código por defecto. Lo único necesario para poder utilizarlo conjuntamente con Azure Connect es habilitar en el apartado Virtual Network de las propiedades del rol el check y pegar el token recuperado anteriormente.
Por último lo configuraremos para poder acceder a él de manera remota. Una vez realizado el paso anterior, subimos la aplicación al portal y comprobamos que la misma aparece en el aparto de Virtual Network dentro de la suscripción.
Por parte del servidor on-premise es necesario instalar de forma manual una aplicación proporcionada desde el portal. Desde dicho servidor pulsamos sobre el botón Install Local Endpoint en la parte superior.
Al hacer click sobre este botón nos facilitará una URL para poder descargar el instalador.
Como bien indica el cuadro de diálogo, este software no puede ser guardado para ser ejecutado dentro de un periodo lejano debido a que tiene un tiempo de expiración. Copiamos el link en el explorador y, una vez descargado, ejecutamos la instalación.
Uno de los inconvenientes con los que nos podemos encontrar llegados a este punto es que, con la fase beta, no podamos ejecutar la instalación si tenemos nuestro sistema operativo en un idioma que no sea inglés .
Cuando la instalación finaliza, vemos que aparece un nuevo icono en la barra de tareas, por el momento, sin conexión con la nube.
A partir de este momento, aparecerán tanto el rol como el servidor on-premise en Activated Endpoints.
Para finalizar la configuración debemos hacer un último paso que es crear el grupo mencionado anteriormente. Para ello pulsamos esta vez sobre Create Group donde deberemos rellenar los siguientes campos:
Como datos obligatorios serán el nombre del grupo, un servidor on-premise en el apartado Connect From y un rol en Connect To.
Lo primero que ocurrirá a partir de ahora será la actualización del web role involucrado.
Y por otro lado el icono del servidor on-premise se tornará al siguiente como señal de conexión con la nube.
Si accedemos en remoto al web role (o desde el servidor on-premise) y abrimos una consola de comandos para hacer un ping a nuestro servidor.
Voilà! ¡Conexión completada!
Si queréis probar cómo sería posible conectar una aplicación en la nube con un SQL Server en un servidor on-premise podéis descargaros el nuevo Windows Azure Training Kit de Diciembre
¡Saludos!
Después de haber repasado los blobs y las tablas, llegó el momento de centrarse en las queues . Como comenté en el post introductorio sobre qué es Windows Azure Storage, las queues se utilizan para almacenar mensajes con el objetivo de conseguir la comunicación entre distintas aplicaciones que trabajan conjuntamente. Estas colas de mensajes son FIFO (First In First Out) y son de un único sentido.
Los mensajes están limitados a 8 KB y deben ser serializables como XML.
Si bien podemos realizar todas las operaciones a través de REST, esto puede resultar algo tedioso a la hora de trabajar. Por ello, podemos hacer uso de la API en .NET para facilitarnos el trabajo. Es necesario añadir una referencia a Microsoft.Windows.Azure y Microsoft.Windows.Azure.StorageClient.
Lo primero que debemos hacer es recuperar la cadena de conexión y crear un CloudQueueClient para poder generar o recuperar las queues.
CloudStorageAccount _account = CloudStorageAccount.DevelopmentStorageAccount;
CloudQueueClient _queueClient = _account.CreateCloudQueueClient();
Al igual que en los blobs, para crear una queue necesitamos recuperar una referencia a la misma aunque esta no exista. Una vez creada llamaremos al método CreateIfNotExist.
var queue = _queueClient.GetQueueReference(«myqueue»);
queue.CreateIfNotExist();
Con ListQueues recuperaremos todas las queues disponibles en esa cuenta.
_queueClient.ListQueues();
Cuando eliminamos una queue, es recomendable limpiar primero su contenido y posteriormente eliminarla a través del método Delete, así como anular su referencia a cualquier variable.
queue.Clear();
queue.Delete();
queue = null;
string message = «Hello world!»;
queue.AddMessage(new CloudQueueMessage(message));
using System.Diagnostics;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;namespace QueueReader_WorkerRole
{
public class WorkerRole : RoleEntryPoint
{
public override void Run()
{
var account = CloudStorageAccount.DevelopmentStorageAccount;
var queueClient = account.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference(«myqueue»);
queue.CreateIfNotExist();while (true)
{
var message = queue.GetMessage();if (message != null)
{
Trace.WriteLine(message.AsString);queue.DeleteMessage(message);
}
else
Thread.Sleep(2000);
}
}public override bool OnStart()
{
ServicePointManager.DefaultConnectionLimit = 12;return base.OnStart();
}
}
}
En este proceso, normalmente ejecutado desde un worker role, lo que estamos haciendo es comprobar cada 2 segundos si existe algún mensaje en la queue y de ser así (si el resultado no es nulo) procesarlo. Una vez finalizado el proceso debemos eliminar el mensaje de la queue para que no sea re procesado de nuevo. Cuando un mensaje es recuperado a través de GetMessage permanece invisible durante 30 segundos por defecto, con el objetivo de que no pueda ser recuperado por nadie más. Este tiempo puede ser extensible hasta 2 horas como máximo y, de no ser procesado el message y posteriormente eliminado, volvería a la queue para que fuera recuperado de nuevo por el mismo worker role o cualquiera de sus instancias.
Existe una alternativa a la hora de conocer el contenido de un mensaje sin la necesidad de sacarlo de la queue. Esta acción es conocida como “peek”, que significa ojear, y puede ser útil para revisar su contenido sin que afecte a su visibilidad. Podemos ojear un mensaje por defecto o indicar a la función PeekMessage el número de mensajes que necesitemos revisar.
var message = queue.PeekMessage();
var messageList = queue.PeekMessage(5);
La cadena de conexión sería exactamente la misma que para cualquiera de los otros dos servicios de Windows Azure Storage.
<Setting value=»DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LDdoajvkA….AUVOdb2ehHw5nN21XI2KF7Q==» />
Espero que sea de utilidad
¡Saludos!
Siguiendo la serie de post relacionados con Windows Azure Storage, hoy me gustaría centrarme en las tablas, donde podemos almacenar datos de una forma estructurada pero no relacional. Este servicio es muy simple, altamente escalable y supone un coste menor que toda una base de datos relacional.
Debido a que no se tratan de tablas relacionales, no podremos:
Antes de comenzar a programar, debemos conocer los tres pasos necesarios para crear nuestra tabla:
La definición de la entidad se trata de una clase con sus correspondientes atributos. Para ser capaces de almacenar nuestra clase en una tabla de Windows Azure Storage necesitaremos además tres atributos adicionales que serán heredados de TableServiceEntity: PartitionKey, RowKey y Timestamp. Los dos primeros necesitamos inicializarlos en el momento de la creación de un nuevo objeto (el lugar ideal sería en el constructor) y el Timestamp será asignado de forma automática. Estas propiedades serán las que nos ayudarán a localizar un registro, y más en concreto PartitionKey será responsable de conseguir una escalabilidad eficiente si lo utilizamos de manera correcta.
Este podría ser un ejemplo de la definición de una entidad:
using System;
using Microsoft.WindowsAzure.StorageClient;namespace StorageManager_MvcWebRole.Models.Tables
{
public class Profile : TableServiceEntity
{public Profile()
{
PartitionKey = «Users»;
RowKey = Guid.NewGuid().ToString();
}public string UserName { get; set; }
public string Email { get; set; }
public int Age { get; set; }
public string BlogUrl { get; set; }
}
}
Una vez que tenemos el qué, podemos saber cómo vamos a manejarlo Creamos una nueva clase que herede de TableServiceContext. Si utilizamos Resharper nos advertirá antes de la compilación de que es necesario importar la librería System.Data.Services.Client.
De otro modo, si compilamos la solución, Visual Studio nos informará del mismo error:
Por otro lado, debemos implementar el constructor heredado de TableServiceContext ya que nos avisa de que no existe un constructor sin parámetros para la clase base y es necesario que la nuestra implemente uno. El motivo es que para crear el contexto de la tabla es necesario tener la dirección donde se aloja la misma, así como las credenciales para acceder.
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;namespace StorageManager_MvcWebRole.Models.Tables
{
public class ProfileTableServiceContext : TableServiceContext
{
private const string TableName = «Profiles»;public ProfileTableServiceContext(string baseAddress, StorageCredentials credentials)
: base(baseAddress, credentials) { }public IQueryable<Profile> Profiles
{
get { return CreateQuery<Profile>(TableName); }
}public void AddProfile(Profile newProfile)
{
AddObject(TableName, newProfile);
SaveChanges();
}public void RemoveProfile(string rowKey)
{
DeleteObject((from item in Profiles
where item.PartitionKey == «Users» && item.RowKey == rowKey
select item).First());
SaveChanges();
}public void UpdateProfile(Profile profileUpdated)
{
var profile = (from item in Profiles
where item.PartitionKey == «Users» && item.RowKey == profileUpdated.RowKey
select item).First();profile.UserName = profileUpdated.UserName;
profile.Age = profileUpdated.Age;
profile.Email = profileUpdated.Email;
profile.BlogUrl = profileUpdated.BlogUrl;UpdateObject(profile);
SaveChanges();
}}
}
Por último ya podemos crear la tabla tanto en la nube como en local. Si bien es un paso que sólo debemos realizar una vez, podemos utilizar una aplicación externa como Cloud Storage Studio o en mi caso he utilizado la clase WebRole.cs que se genera cuando creamos un proyecto de tipo Windows Azure Project.
using System.Configuration;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using StorageManager_MvcWebRole.Models.Tables;namespace StorageManager_MvcWebRole
{
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
configSetter(ConfigurationManager.ConnectionStrings[configName].ConnectionString));var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
CloudTableClient.CreateTablesFromModel(typeof(ProfileTableServiceContext), storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);return base.OnStart();
}
}
}
Si quisiéramos conectar con una tabla en la nube, la cadena de conexión sería similar a la siguiente:
<Setting name=»StorageAccount» value=»DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LDdoajvkAIKzi98CH…..D1PJVpAUVOdb2ehHw5nN21XI2KF7Q==» />
Ya tenemos todos los ingredientes necesarios para trabajar con nuestra nueva tabla Lo único que faltaría sería usar el contexto para relacionarnos con la misma. Para realizar este ejemplo he creado un proyecto ASP.NET MVC y en pocas líneas hago uso de cada una de las acciones posibles:
using System;
using System.Linq;
using System.Web.Mvc;
using Microsoft.WindowsAzure;
using StorageManager_MvcWebRole.Models.Tables;namespace StorageManager_MvcWebRole.Controllers
{
public class TableController : Controller
{
private readonly CloudStorageAccount _account;
private readonly ProfileTableServiceContext _profileServiceContext;public TableController()
{
_account = CloudStorageAccount.DevelopmentStorageAccount;
_profileServiceContext = new ProfileTableServiceContext(_account.TableEndpoint.ToString(), _account.Credentials);
}public ActionResult Index()
{
return View(_profileServiceContext.Profiles);
}public ActionResult Create()
{
return View();
}[HttpPost]
public ActionResult Create(Profile newProfile)
{
_profileServiceContext.AddProfile(newProfile);return RedirectToAction(«Index»);
}public ActionResult Delete(string rowKey)
{
_profileServiceContext.RemoveProfile(rowKey);return RedirectToAction(«Index»);
}public ActionResult Edit(string rowKey)
{
return View((from profile in _profileServiceContext.Profiles
where profile.PartitionKey == «Users» && profile.RowKey == rowKey
select profile).First());}
[HttpPost]
public ActionResult Edit(Profile profileUpdated)
{
_profileServiceContext.UpdateProfile(profileUpdated);return RedirectToAction(«Index»);
}
}
}
Espero que sea de utilidad
¡Saludos!
La palabra Blob se corresponde con las siglas de Binary Large OBject y tiene como objetivo el almacenamiento de archivos de gran tamaño, como por ejemplo:
Cada archivo corresponde a un blob y cada blob está contenido a su vez en un container. Para que os hagáis una idea, un ejemplo podría ser el siguiente: Tengo una cuenta de storage, a la que puse por nombre MediaStorage, donde quiero almacenar mis archivos de música. A su vez, me gustaría tener un container para separar mis archivos por género pop y rock.
Visto esto, podemos decir que un container se trata de una especie de carpeta, la cual agrupa nuestros blobs.
En este post voy a centrarme en un wrapper disponible a través del SDK de Windows Azure para encapsular las llamadas REST necesarias para cada una de las opciones.
Necesitaremos importar Microsoft.Windows.Azure y Microsoft.Windows.Azure.StorageClient.
Si A día de hoy se llama Storage Emulator y podemos trabajar con blobs, tablas y colas.
La forma más sencilla es a través de Visual Studio 2010. En la ventana Server Explorer podemos ver los archivos almacenados en cada uno de los containers.
Al igual que podemos visualizar nuestro entorno de desarrollo, podríamos adjuntar una cuenta de Storage en la nube y ver su contenido.
Mientras estamos creando la aplicación, podemos utilizar el entorno de desarrollo local para realizar las pruebas necesarias. El código sería el siguiente:
CloudStorageAccount _account = CloudStorageAccount.DevelopmentStorageAccount;
CloudBlobClient _blobClient = new CloudBlobClient(_account.BlobEndpoint, _account.Credentials);
Una vez finalizado el desarrollo, sería necesario modificar la primera línea para recuperar los valores del archivo de configuración.
CloudStorageAccount.SetConfigurationSettingPublisher((configName,configSetter) => configSetter(RoleEnviroment.GetConfigurationSettingValue(configName)));
CloudStorageAccount _account = CloudStorageAccount.FromConfigurationSetting(«StorageAccount»);
CloudBlobClient _blobClient = new CloudBlobClient(_account.BlobEndpoint, _account.Credentials);
Un ejemplo de cadena de conexión válida podría ser el siguiente:
<Setting name=»StorageAccount» value=»DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LD …. +4D1PJVpAUVOdb2ehHw5nN21XI2KF7Q==» />
Lo primero que debemos crear es un contenedor donde almacenar nuestros blobs ya que estos últimos no pueden ser creados si no están dentro de alguno.
private CloudBlobContainer GetContainer(string containerName)
{
var cloudBlobContainer = _blobClient.GetContainerReference(containerName);
if (cloudBlobContainer.CreateIfNotExist())
{
var blobContainerPermissions = cloudBlobContainer.GetPermissions();
blobContainerPermissions.PublicAccess = BlobContainerPublicAccessType.Container;
cloudBlobContainer.SetPermissions(blobContainerPermissions);
}
return cloudBlobContainer;
}
Con el método CreateIfNotExist nos aseguramos de que el mismo sea generado si no fue creado con anterioridad. Si es la primera vez , este método devolverá true y le asignaremos los permisos para que un usuario anónimo pueda acceder al contenido.
Para la creación de un blob, únicamente debemos recuperar el container donde queremos que se aloje y «simular» su recuperación a través de GetBlobReference. Llegados a este punto se creará un nuevo objeto del tipo CloudBlob a través del cual podremos subir un nuevo archivo a la nube.
public void SaveBlob(Stream file, string filename)
{
var blob = GetContainer(«myContainer»).GetBlobReference(filename);
blob.UploadFromStream(file);
}
En este caso he utilizado el método UploadFromStream pero es importante saber que tenemos otros métodos para realizar la subida de archivos:
Para eliminar un blob debemos, en primer lugar, recuperar el contenedor (he utilizado el método anterior para ello), recuperar el blob y finalmente llamar al método Delete del mismo.
public void Delete(string uri, string containerName)
{
var container = GetContainer(containerName);
var blob = container.GetBlobReference(uri);
blob.Delete();
}
public void Copy(string uri, string containerName)
{
var container = GetContainer(containerName);
var blob = container.GetBlobReference(uri);
var newBlob = container.GetBlobReference(string.Format(«Copy of {0}», blob.Uri.Segments[blob.Uri.Segments.Length – 1]));
newBlob.CopyFromBlob(blob);
}
public void Snapshot(string uri, string containerName)
{
var container = GetContainer(containerName);
var blob = container.GetBlobReference(uri);
blob.CreateSnapshot();
}
Los snapshots proporcionan una versión sólo de lectura de un blob. Esta funcionalidad puede ser útil para restaurar una versión anterior de un blob después de ser modificado. Sin embargo, una copia es un blob distinto ,creado a partir de otro, el cual se puede modificar.
public void AddMetadata(string uri, string containerName)
{
var container = GetContainer(containerName);
var blob = container.GetBlobReference(uri);
var metadata = new NameValueCollection();
metadata[«Language»] = «es»;
metadata[«Date»] = DateTime.Now.ToShortTimeString();
blob.Metadata.Add(metadata);
}
Espero que sea de utilidad 🙂
¡Saludos!