Xamarin Forms – Bilder als Blob in Azure Storage Account speichern und lesen

Als ich ein Schulprojekt etwas neues als Data Layer benutzen wollte, kam mir Azure Storage Account im Sinn. Ich habe aber schnell gemerkt, dass es sich eher um eine neuere Technologie (in Vergleich mit traditionelle Datenbanken wie zB MySQL) handelt, da ich nur wenig darüber Dokumentiert gefunden habe, vor allem bei Benutzung in Zusammenhang mit Xamarin Forms, was ich bei meinem Beispiel benutze. Ich habe jetzt viel darüber gegoogelt und ausprobiert und bin zu eine Lösung gekommen wie man Bilder Speichern und lesen kann.

In diesem Blog Post werde ich kurz erklären was Azure Storage Account ist und danach gibt es ein kurzen Tutorial wie man Bilder in Azure Storage Account speichern und lesen kann. Beim Tutorial werde ich das Projekt vom Xamarin – Einstieg zu Dependency Services mit eine eigene Picture Picker” benutzten.

Inhalt

  • “Azure Storage Account”, “Azure Storage Account” oder doch “Windows Azure Storage”?
  • Was ist Azure Storage Account?
  • Azure Storage Account aufsetzten
  • Azure Storage  Account Verbindung in Xamarin Forms erstellen
  • Blob in Azure speichern
  • Blob aus Azure lesen

“Azure Storage Account”, “Microsoft Azure Storage” oder doch “Windows Azure Storage”?

Am Anfang war ich sehr verwirrt, ich war unsicher ob es verschiedenen arten von Azure Storage gab, da den Namen nicht 100% einheitlich präsentiert wird.

AzureStorageAccounts
“Azure storage accounts” von https://docs.microsoft.com/en-us/azure/storage/storage-create-storage-account
MicrosoftAzureStorage_Video
“Microsoft Azure Storage” von https://azure.microsoft.com/en-us/services/storage/?v=16.50
WindowsAzureStorage
“Microsoft WindowsAzure Storage” von Nuget https://www.nuget.org/packages/WindowsAzure.Storage

Welcher den korrekten Namen ist, kann ich nicht sagen, aber meistens wird den Begriff “Storage Account” benutzt.

Was ist Azure Storage Account?

Azure Storage Account ist Microsofts Cloud Speicher Lösung, welcher Möglichkeiten für das Speicher von Files, NoSQL Datensätze, Queues und Blobs anbieten.
Wenn du etwas in diese Liste nicht kennt, ist das überhaupt kein Problem, nur weil man Azure Storage Account benutzt, muss man nicht alle diese Funktionen benutzten, man kann auch den Storage Account zum Beispiel nur für das Abspeichern von Bildern und Logfiles benutzen.

Pros von Azure Storage Account:

  • Sehr einfach skalierbar
  • Sehr robust
  • Load Balancer in the box
  • Dank Cloud Lösung von der ganzen Welt erreichbar
  • Pay Per Use (Nur für das Bezahlen was man benutzt)
  • In mehreren Programmiersprachen verfügbar wie NET, Java, Node.js, Python, Ruby, PHP, C++ und per REST API

Cons von Azure Storage Account:

  • Gute aber kurze Dokumentation
  • Sehr kleines Community, siehe Bilder unten
  • Steile Lernkurve (Im Sinn von Schwierige Anfang)

Auch wenn der Azure Storage Account Service neu ist, ist sie schon stark am wachsen:

AzureAccountStorageTrend_Alone
Google Trends “Azure Storage”

Jedoch hat der Service noch eine weile um mit den Amazon Service äquivalent (Amazon S3) zu Kämpfen und wenn man mit eine mehr bekannte Data Layer Lösung wie MongoDB ist das Azure Storage Account fast winzig:

AzureAccountStorageTrend_MonboDB_AmazonS3
Google Trends “Azure Storage”(BLAU), “Amazon S3″(ROT) und “MongoDB”(GELB-ORANGE)

Tutorial

Bei diesem Tutorial wird vorausgesetzt das du:

Azure Storage Account aufsetzten

  1. Log dich auf www.portal.azure.com ein.
  2. Gehe auf “Storage Accounts”
    OpenStorageAccounts
  3. Klicke als nächstes auf dem “+” Knopf oben und gebe die Details ein, um ein Account Storage zu erstellen.
    AddAndThenFillOutInformation

Azure Storage Account Verbindung in Xamarin Forms erstellen

Es gibt verschiedene Arten, wie du dich mit ein Storagte Account verbinden kannst, es wird aber stark empfohlen die Access Keys für alles was kein “Demo-Projekt” ist, zu benutzten.
Mehr Info zur Security bei Storage Accounts findest du auf: Storage-Security Guide

  1. Öffne deine “Access Keys” in deinem neu erstellten Storage Account.
    Kopiere die “Primary” oder die “Secondary” Connection String.
    SignatureKeys
  2. Öffne dein Projekt in Visual Studio und mach den Nuget Packet Manger durch Rechtsklick auf dem Solution -> “Manage Nuget packages for solution” auf und lade “WindowsAzure.Storage” runter.
  3. Erstelle als nächstes eine Klasse mit den Namen “BlobService”.
  4. Füge folgende Code dazu:
    private static readonly Random Random = new Random();
    private readonly CloudStorageAccount _storageAccount;
    private readonly CloudBlobClient _blobClient;
    public BlobService(CloudStorageAccount storageAccount)
    {
    _storageAccount = storageAccount;
    _blobClient = _storageAccount.CreateCloudBlobClient();
    }
  5.  Erstelle eine Klasse mit den Namen “ExampleRepository”.
  6. Füge folgende Code dazu (vergesse nicht den Key-Platzhalter mit deinen eigenen Key zu ersetzten):
    private readonly CloudStorageAccount _storageAccount;
    private readonly BlobService _blobService;
    public ExampleRepository()
    {
    _storageAccount =
    CloudStorageAccount.Parse(                                               "DefaultEndpointsProtocol=https;AccountName=kfcevents;AccountKey=       {INSERT_YOUR_KEY_HERE};EndpointSuffix=core.windows.net");
    _blobService = new BlobService(_storageAccount);
    }
    public async Task AddWithStream(Stream stream)
    {
    string name = await _blobService.SaveBlobAsync("images", stream);
    return name;
    }
  7. Wenn man der Connection nicht testen will, bitte zum Abschnitt “Blob in Azure speichern” weitergehen.
    Um der Connection zu Testen muss man zuerst folgende Code zum “BlobService” hinzufügen:
    public async Task PerformBlobOperation()
    {
    // Create the blob client.
    CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();
    // Retrieve reference to a previously created container.
    CloudBlobContainer container =                                           blobClient.GetContainerReference("testcontainer1");
    // Create the container if it doesn't already exist.
    await container.CreateIfNotExistsAsync();
    // Retrieve reference to a blob named "myblob".
    CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob1");
    // Create the "myblob" blob with the text "Hello, world!"
    await blockBlob.UploadTextAsync("Hello world");
    }
  8. Jetzt müssen wir nur noch der Methode Aufruf zu unser Button Event hinzufügen:
    AddTestConnectionMethodToButtonEvent
  9. Nach dem Testen der Methode und Methoden Aufruf wieder löschen, dies ist nur um zu kontrollieren, dass wir eine gültige Connection String haben und dass wir alles richtig aufgesetzt haben.

Blob in Azure speichern

Jetzt kommen wir zur spannende Teil, wie wir die Bilder in unsere Storage Account speichern. Es gibt hier mehr als eine Lösung und für diejenige, die alle Möglichkeiten vergleichen wollen oder in allgemein einfach ein bisschen mehr über Blobs in Storage Accounts lernen möchten empfehle ich ein Besuch auf: Microsoft – Get started with Azure Blob Storage

Bei diesem Tutorial werden wir den Stream von unserem PicturePicker benutzen, um die Bilder hochzuladen.

    1. Öffne den BlobService und füge folgende zwei Methoden hinzu
      Methode 1
      Eine einfach Methode um Zufall-Strings zu erzeugen.
      (Dies ist nicht empfohlen für eine richtige Applikation, es ist explizit nur für diesen Blog Post gedacht.)
      private static string RandomString(int length)
      {
      const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      return new string(Enumerable.Repeat(chars, length)
      .Select(s => s[Random.Next(s.Length)]).ToArray());
      }

      Methode 2
      Mit diese Methode speichern wird ein Bild, welcher wir per Stream übergeben in ein Container mit den mitgegebenen Containername.
      public async Task SaveBlobAsync(string containerName, Stream stream)
      {
      //Get Container Reference from @param "containerName" and create     it if it doesn't exist yet.
      CloudBlobContainer container =                                       _blobClient.GetContainerReference(containerName.ToLower());
      await container.CreateIfNotExistsAsync();
      //Get a random string with 12 characters
      string name = RandomString(12);
      // Retrieve reference to a blob with the randomstring name from       above.
      CloudBlockBlob blockBlob = container.GetBlockBlobReference(name);
      // Create the "myblob" blob with the text "Hello, world!"
      await blockBlob.UploadFromStreamAsync(stream);
      return name;
      }
    2. Gehe jetzt zum ExampleRepository und füge folgende Methode dazu:
      public async Task AddWithStream(Stream stream)
      {
      string name = await _blobService.SaveBlobAsync("flyers", stream);
      return name;
      }

      Diese Methode ruft der vorher hinzugefügten Methode im BlobService auf und gibt den Namen vom Bild zurück.
    3. Jetzt müssen wir nur noch die neue Methode “AddWithStream” von unsere ClickEvent aufrufen.
      Dies machen wir durch folgende Code:
      _imageName = await _storageEventRepository.AddWithStream(stream);
      Und schon speichern wir das Bild in der Cloud!

Blob aus Azure lesen

  1. Als erstes brauchen wir wieder eine neue Methode in unserem BlobService.cs:
    public async Task<byte[]> GetImage(string name)
    {
    var container = GetContainer();
    //Gets the block blob representing the image
    var blob = container.GetBlobReference(name);
    if (await blob.ExistsAsync())
    {
    // Gets the block blob length to initialize the array in memory
    await blob.FetchAttributesAsync();
    byte[] blobBytes = new byte[blob.Properties.Length];
    // Downloads the block blob and stores the content in an array in memory
    await blob.DownloadToByteArrayAsync(blobBytes, 0);
    return blobBytes;
    }
    return null;
    }

    Mit diese Methode, holen wir das Bild dem entsprechende Name aus der Azure Storage und geben es als ein ByteArray zurück.
  2. Als nächstes brauchen wir ein Methodenaufruf von unsere Repository Schnittstelle (ExampleRepository.cs):
    public async Task<byte[]> GetImageByName(string imageName)
    {
    byte[] image = await _blobService.GetImage(imageName);
    return image;
    }
  3. Jetzt müssen wir nur noch unser ClickEvent anpassen, zum das Bild von unser Azure Storage zu laden, statt direkt von unserem PicturePicker.
    Jetzt diese Lösung macht nicht so viel Sinn, da wir nichts langfristiges abspeichern, aber die Macht liegt jetzt in deine Hände, jetzt kannst du den Code wie du willst manipulieren um deine Ideen zu verwirklichen.
    private async void ImagePickerOnClicked(object sender, EventArgs eventArgs)
    {
    var stream = await DependencyService.Get().GetImageStreamAsync();
    if (stream != null)
    {
    _imageName = await _storageEventRepository.AddWithStream(stream);
    Byte[] byteArray = await _storageEventRepository.GetImageByName(_imageName);
    SelectedImage.Source = ImageSource.FromStream(() => new MemoryStream(byteArray));
    }
    }

    ClickEventFinish
    Click Event
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s