Almacenamiento y acceso a datos en Azure Storage desde Xamarin.Forms

Azure Storage es una solución escalable de almacenamiento en la nube que se puede usar para almacenar datos estructurados y no estructurados. En este artículo se muestra cómo usar Xamarin.Forms para almacenar texto y datos binarios en Azure Storage y cómo acceder a los datos.

Azure Storage proporciona cuatro servicios de almacenamiento:

  • Blob Storage. Un blob puede ser datos binarios o de texto, como copias de seguridad, máquinas virtuales, archivos multimedia o documentos.
  • Table Storage es un almacén de atributos clave noSQL.
  • Queue Storage es un servicio de mensajería para el procesamiento de flujos de trabajo y la comunicación entre servicios en la nube.
  • File Storage proporciona almacenamiento compartido mediante el protocolo SMB.

Existen dos tipos de cuentas de almacenamiento:

  • Una cuenta de almacenamiento de uso general proporciona acceso a los servicios de Azure Storage desde una sola cuenta.
  • Una cuenta de Blob Storage es una cuenta de almacenamiento especializada para almacenar blobs. Este tipo de cuenta se recomienda cuando solo necesita almacenar datos de blobs.

En este artículo y en la aplicación de ejemplo que acompaña, se muestra cómo cargar archivos de imagen y texto en Blob Storage y descargarlos. Además, también muestra cómo recuperar una lista de archivos de Blob Storage y eliminar archivos.

Para obtener más información sobre Azure Storage, consulte Introducción a Storage.

Nota:

Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

Introducción a Blob Storage

Blob Storage consta de tres componentes, que se muestran en el diagrama siguiente:

Descripción de Blob Storage

Todo el acceso a Azure Storage es a través de una cuenta de almacenamiento. Una cuenta de almacenamiento puede contener un número ilimitado de contenedores y un contenedor puede almacenar un número ilimitado de blobs, hasta el límite de capacidad de la cuenta de almacenamiento.

Un blob es un archivo de cualquier tipo y tamaño. Azure Storage admite tres tipos de blobs diferentes:

  • Los blobs en bloques están optimizados para el streaming y el almacenamiento de objetos en la nube, y son una buena opción para almacenar copias de seguridad, archivos multimedia, documentos, etc. Los blobs en bloques pueden tener un tamaño de hasta 195 Gb.
  • Los blobs en anexos son similares a los blobs en bloques, pero están optimizados para operaciones de anexión, como el registro. Los blobs en anexos pueden tener un tamaño de hasta 195 Gb.
  • Los blobs en páginas están optimizados para operaciones frecuentes de lectura y escritura y normalmente se usan para almacenar máquinas virtuales y sus discos. Los blobs en páginas pueden tener un tamaño de hasta 1 Tb.

Nota:

Tenga en cuenta que las cuentas de Blob Storage admiten blobs en bloques y en anexos, pero no blobs en páginas.

Un blob se carga en Azure Storage y se descarga de Azure Storage como un flujo de bytes. Por lo tanto, los archivos se deben convertir en una secuencia de bytes antes de cargarlos y volver a su representación original después de la descarga.

Cada objeto almacenado en Azure Storage tiene una dirección URL única. El nombre de la cuenta de almacenamiento forma el subdominio de esa dirección y la combinación de subdominio y nombre de dominio forma un punto de conexión para la cuenta de almacenamiento. Por ejemplo, si la cuenta de almacenamiento se denomina mystorageaccount, el punto de conexión de blob predeterminado para la cuenta de almacenamiento es https://mystorageaccount.blob.core.windows.net.

La dirección URL para el acceso a un objeto en una cuenta de almacenamiento se crea anexando la ubicación del objeto en la cuenta de almacenamiento al extremo. Por ejemplo, una dirección de blob tendrá el formato https://mystorageaccount.blob.core.windows.net/mycontainer/myblob.

Configuración

El proceso para integrar una cuenta de Azure Storage en una aplicación Xamarin.Forms es el siguiente:

  1. Cree una cuenta de almacenamiento. Para obtener más información, consulte Creación de una cuenta de almacenamiento.
  2. Agregue la biblioteca cliente de Azure Storage a la aplicación Xamarin.Forms.
  3. Configure la cadena de conexión de almacenamiento. Para más información, consulte Conexión a Azure Storage.
  4. Agregue directivas using para los espacios de nombres Microsoft.WindowsAzure.Storage y Microsoft.WindowsAzure.Storage.Blob a las clases que tendrán acceso a Azure Storage.

Conexión a Azure Storage

Todas las solicitudes realizadas en los recursos de la cuenta de almacenamiento deben autenticarse. Aunque los blobs se pueden configurar para admitir la autenticación anónima, hay dos enfoques principales que una aplicación puede usar para autenticarse con una cuenta de almacenamiento:

  • Clave compartida. Este enfoque usa el nombre de la cuenta de Azure Storage y la clave de cuenta para acceder a los servicios de almacenamiento. A una cuenta de almacenamiento se le asignan dos claves privadas en la creación que se pueden usar para la autenticación de claves compartidas.
  • Firma de acceso compartido. Se trata de un token que se puede anexar a una dirección URL que permite el acceso delegado a un recurso de almacenamiento, con los permisos que especifica, durante el período de tiempo que es válido.

Se pueden especificar cadenas de conexión que incluyan la información de autenticación necesaria para acceder a los recursos de Azure Storage desde una aplicación. Además, se puede configurar un cadena de conexión para conectarse al emulador de Azure Storage desde Visual Studio.

Nota:

Azure Storage admite HTTP y HTTPS en una cadena de conexión. Sin embargo, se recomienda usar HTTPS.

Conexión al emulador de Azure Storage

El emulador de Azure Storage proporciona un entorno local que emula los servicios de blob, cola y tabla de Azure para fines de desarrollo.

La siguiente cadena de conexión debe usarse para conectarse al emulador de Azure Storage:

UseDevelopmentStorage=true

Para más información sobre el emulador de Azure Storage, consulte Uso del emulador de Azure Storage para desarrollo y pruebas.

Conectar a Azure Storage mediante una clave compartida

El siguiente formato cadena de conexión debe usarse para conectarse a Azure Storage con una clave compartida:

DefaultEndpointsProtocol=[http|https];AccountName=myAccountName;AccountKey=myAccountKey

myAccountName debe reemplazarse por el nombre de la cuenta de almacenamiento y myAccountKey debe reemplazarse por una de las dos claves de acceso de la cuenta.

Nota:

Al usar la autenticación de clave compartida, el nombre de la cuenta y la clave de cuenta se distribuirán a cada persona que use la aplicación, lo que proporcionará acceso completo de lectura y escritura a la cuenta de almacenamiento. Por lo tanto, use la autenticación de clave compartida solo con fines de prueba y nunca distribuya claves a otros usuarios.

Conexión a Azure Storage mediante una firma de acceso compartido

El siguiente formato de cadena de conexión debe usarse para conectarse a Azure Storage con una SAS:

BlobEndpoint=myBlobEndpoint;SharedAccessSignature=mySharedAccessSignature

myBlobEndpoint debe reemplazarse por la dirección URL del punto de conexión de blob y mySharedAccessSignature debe reemplazarse por la SAS. La SAS proporciona el protocolo, el punto de conexión de servicio y las credenciales para acceder al recurso.

Nota:

Se recomienda la autenticación de SAS para aplicaciones de producción. Sin embargo, en una aplicación de producción, la SAS debe recuperarse de un servicio back-end a petición, en lugar de empaquetarse con la aplicación.

Para obtener más información sobre las firmas de acceso compartido, consulte Uso de firmas de acceso compartido (SAS).

Creación de un contenedor

El método GetContainer se usa para recuperar una referencia a un contenedor con nombre, que luego se puede usar para recuperar blobs del contenedor o para agregar blobs al contenedor. El siguiente ejemplo de código muestra el método GetContainer:

static CloudBlobContainer GetContainer(ContainerType containerType)
{
  var account = CloudStorageAccount.Parse(Constants.StorageConnection);
  var client = account.CreateCloudBlobClient();
  return client.GetContainerReference(containerType.ToString().ToLower());
}

El método CloudStorageAccount.Parse analiza una cadena de conexión y devuelve una instancia de CloudStorageAccount que representa la cuenta de almacenamiento. A continuación, el método CreateCloudBlobClient crea una instancia CloudBlobClient, que se usa para recuperar contenedores y blobs. El método GetContainerReference recupera el contenedor especificado como una instancia CloudBlobContainer, antes de que se devuelva al método de llamada. En este ejemplo, el nombre del contenedor es el valor de enumeración ContainerType, convertido en una cadena minúscula.

Nota:

Los nombres de contenedor deben estar en minúsculas y deben comenzar con una letra o un número. Además, solo pueden contener letras, números y el carácter de guión, y deben tener entre 3 y 63 caracteres de longitud.

El método GetContainer se invoca de la siguiente manera:

var container = GetContainer(containerType);

La instancia CloudBlobContainer se puede usar para crear un contenedor si aún no existe:

await container.CreateIfNotExistsAsync();

De forma predeterminada, un contenedor recién creado es privado. Esto significa que se debe especificar una clave de acceso de almacenamiento para recuperar blobs del contenedor. Para obtener información sobre cómo crear blobs dentro de un contenedor público, consulte Creación de un contenedor.

Cargar datos en un contenedor

El método UploadFileAsync se usa para cargar un flujo de datos de bytes en Blob Storage y se muestra en el ejemplo de código siguiente:

public static async Task<string> UploadFileAsync(ContainerType containerType, Stream stream)
{
  var container = GetContainer(containerType);
  await container.CreateIfNotExistsAsync();

  var name = Guid.NewGuid().ToString();
  var fileBlob = container.GetBlockBlobReference(name);
  await fileBlob.UploadFromStreamAsync(stream);

  return name;
}

Después de recuperar una referencia de contenedor, el método crea el contenedor si aún no existe. A continuación, se crea un nuevo Guid para que actúe como un nombre de blob único y se recupera una referencia de bloque de blobs como una instancia CloudBlockBlob. A continuación, el flujo de datos se carga en el blob mediante el método UploadFromStreamAsync, que crea el blob si aún no existe o lo sobrescribe si existe.

Antes de que un archivo se pueda cargar en Blob Storage mediante este método, primero debe convertirse en una secuencia de bytes. Esto se muestra en el ejemplo de código siguiente:

var byteData = Encoding.UTF8.GetBytes(text);
uploadedFilename = await AzureStorage.UploadFileAsync(ContainerType.Text, new MemoryStream(byteData));

Los datos text se convierten en una matriz de bytes, que luego se ajusta como una secuencia que se pasa al método UploadFileAsync.

Descargar datos de un contenedor

El método GetFileAsync se usa para descargar datos de blobs de Azure Storage y se muestra en el ejemplo de código siguiente:

public static async Task<byte[]> GetFileAsync(ContainerType containerType, string name)
{
  var container = GetContainer(containerType);

  var blob = container.GetBlobReference(name);
  if (await blob.ExistsAsync())
  {
    await blob.FetchAttributesAsync();
    byte[] blobBytes = new byte[blob.Properties.Length];

    await blob.DownloadToByteArrayAsync(blobBytes, 0);
    return blobBytes;
  }
  return null;
}

Después de recuperar una referencia de contenedor, el método recupera una referencia de blob para los datos almacenados. Si el blob existe, el método FetchAttributesAsync recupera sus propiedades. Se crea una matriz de bytes del tamaño correcto y el blob se descarga como una matriz de bytes que se devuelve al método de llamada.

Después de descargar los datos de bytes de blob, debe convertirse en su representación original. Esto se muestra en el ejemplo de código siguiente:

var byteData = await AzureStorage.GetFileAsync(ContainerType.Text, uploadedFilename);
string text = Encoding.UTF8.GetString(byteData);

El método recupera la matriz de bytes de Azure Storage GetFileAsync antes de convertirla en una cadena codificada UTF8.

Enumeración de datos en un contenedor

El método GetFilesListAsync se usa para recuperar una lista de blobs almacenados en un contenedor y se muestra en el ejemplo de código siguiente:

public static async Task<IList<string>> GetFilesListAsync(ContainerType containerType)
{
  var container = GetContainer(containerType);

  var allBlobsList = new List<string>();
  BlobContinuationToken token = null;

  do
  {
    var result = await container.ListBlobsSegmentedAsync(token);
    if (result.Results.Count() > 0)
    {
      var blobs = result.Results.Cast<CloudBlockBlob>().Select(b => b.Name);
      allBlobsList.AddRange(blobs);
    }
    token = result.ContinuationToken;
  } while (token != null);

  return allBlobsList;
}

Después de recuperar una referencia de contenedor, el método usa el método ListBlobsSegmentedAsync del contenedor para recuperar las referencias a los blobs del contenedor. Los resultados devueltos por el método ListBlobsSegmentedAsync se enumeran mientras la instancia BlobContinuationToken no es null. Cada blob se convierte desde el IListBlobItem devuelto a un CloudBlockBlob para acceder a la propiedad Name del blob, antes de agregar el valor a la colección allBlobsList. Una vez que la instancia BlobContinuationToken es null, se ha devuelto el nombre del último blob y la ejecución sale del bucle.

Eliminación de datos de un contenedor

El método DeleteFileAsync se usa para eliminar un blob de un contenedor y se muestra en el ejemplo de código siguiente:

public static async Task<bool> DeleteFileAsync(ContainerType containerType, string name)
{
  var container = GetContainer(containerType);
  var blob = container.GetBlobReference(name);
  return await blob.DeleteIfExistsAsync();
}

Después de recuperar una referencia de contenedor, el método recupera una referencia de blob para el blob especificado. A continuación, el blob se elimina con el método DeleteIfExistsAsync.