[Storage] Azure Blob Storage

とりあえずバイナリーファイルを（イメージや動画など）保存するときは Blob Storageに保存するような設計をしています。安価かつコントロールしやすくお勧めです。

サービスサイトはこちら
https://azure.microsoft.com/ja-jp/services/storage/blobs/

# 必要なもの

- Azure アカウント
- Visual Studio

# ここでカバーされる範囲

- `Blobの`構成
- クライアントライブラリーのダウンロード
- `Container`の作成、ファイルのアップロード、 `Container`の削除
- ファイルのダウンロード、ファイルの削除
- `Container`内のファイル一覧を表示

# Blobの構成

`Blob`の構成は下記のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/8904299c-76aa-84e7-c8df-68c256a8ed72.png)

`Account`の基に`Container`（複数）があり、そのコンテイナーの中に`Blob`があります。

# クライアントライブラリーのダウロード

まずはクライアントライブラリー V12 を入手します。

```
Install-Package Azure.Storage.Blobs -Version 12.1.0
```
Nugetの詳細はこちら
https://www.nuget.org/packages/Azure.Storage.Blobs/


# サンプルコード

では、さっそくサンプルコードを見てみます。

```csharp

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using NUnit.Framework;

namespace Azure.Storage.Blobs.Samples
{
    /// <summary>
    /// Basic Azure Blob Storage samples
    /// </summary>
    public class Sample01b_HelloWorldAsync : SampleTest
    {
        /// <summary>
        /// Upload a file to a blob.
        /// </summary>
        [Test]
        public async Task UploadAsync()
        {
            // Create a temporary Lorem Ipsum file on disk that we can upload
            string path = CreateTempFile(SampleFileContent);

            // Get a connection string to our Azure Storage account.  You can
            // obtain your connection string from the Azure Portal (click
            // Access Keys under Settings in the Portal Storage account blade)
            // or using the Azure CLI with:
            //
            //     az storage account show-connection-string --name <account_name> --resource-group <resource_group>
            //
            // And you can provide the connection string to your application
            // using an environment variable.
            string connectionString = ConnectionString;

            // Get a reference to a container named "sample-container" and then create it
            BlobContainerClient container = new BlobContainerClient(connectionString, Randomize("sample-container"));
            await container.CreateAsync();
            try
            {
                // Get a reference to a blob
                BlobClient blob = container.GetBlobClient(Randomize("sample-file"));

                // Open the file and upload its data
                using (FileStream file = File.OpenRead(path))
                {
                    await blob.UploadAsync(file);
                }

                // Verify we uploaded some content
                BlobProperties properties = await blob.GetPropertiesAsync();
                Assert.AreEqual(SampleFileContent.Length, properties.ContentLength);
            }
            finally
            {
                // Clean up after the test when we're finished
                await container.DeleteAsync();
            }
        }

        /// <summary>
        /// Download a blob to a file.
        /// </summary>
        [Test]
        public async Task DownloadAsync()
        {
            // Create a temporary Lorem Ipsum file on disk that we can upload
            string originalPath = CreateTempFile(SampleFileContent);

            // Get a temporary path on disk where we can download the file
            string downloadPath = CreateTempPath();

            // Get a connection string to our Azure Storage account.
            string connectionString = ConnectionString;

            // Get a reference to a container named "sample-container" and then create it
            BlobContainerClient container = new BlobContainerClient(connectionString, Randomize("sample-container"));
            await container.CreateAsync();
            try
            {
                // Get a reference to a blob named "sample-file"
                BlobClient blob = container.GetBlobClient(Randomize("sample-file"));

                // First upload something the blob so we have something to download
                await blob.UploadAsync(File.OpenRead(originalPath));

                // Download the blob's contents and save it to a file
                BlobDownloadInfo download = await blob.DownloadAsync();
                using (FileStream file = File.OpenWrite(downloadPath))
                {
                    await download.Content.CopyToAsync(file);
                }

                // Verify the contents
                Assert.AreEqual(SampleFileContent, File.ReadAllText(downloadPath));
            }
            finally
            {
                // Clean up after the test when we're finished
                await container.DeleteAsync();
            }
        }

        /// <summary>
        /// Download our sample image.
        /// </summary>
        [Test]
        public async Task DownloadImageAsync()
        {
            string downloadPath = CreateTempPath();
            #region Snippet:SampleSnippetsBlob_Async
            // Get a temporary path on disk where we can download the file
            //@@ string downloadPath = "hello.jpg";

            // Download the public blob at https://aka.ms/bloburl
            await new BlobClient(new Uri("https://aka.ms/bloburl")).DownloadToAsync(downloadPath);
            #endregion

            Assert.IsTrue(File.ReadAllBytes(downloadPath).Length > 0);
            File.Delete("hello.jpg");
        }

        /// <summary>
        /// List all the blobs in a container.
        /// </summary>
        [Test]
        public async Task ListAsync()
        {
            // Get a connection string to our Azure Storage account.
            string connectionString = ConnectionString;

            // Get a reference to a container named "sample-container" and then create it
            BlobContainerClient container = new BlobContainerClient(connectionString, Randomize("sample-container"));
            await container.CreateAsync();
            try
            {
                // Upload a couple of blobs so we have something to list
                await container.UploadBlobAsync("first", File.OpenRead(CreateTempFile()));
                await container.UploadBlobAsync("second", File.OpenRead(CreateTempFile()));
                await container.UploadBlobAsync("third", File.OpenRead(CreateTempFile()));

                // List all the blobs
                List<string> names = new List<string>();
                await foreach (BlobItem blob in container.GetBlobsAsync())
                {
                    names.Add(blob.Name);
                }

                Assert.AreEqual(3, names.Count);
                Assert.Contains("first", names);
                Assert.Contains("second", names);
                Assert.Contains("third", names);
            }
            finally
            {
                // Clean up after the test when we're finished
                await container.DeleteAsync();
            }
        }

        /// <summary>
        /// Trigger a recoverable error.
        /// </summary>
        [Test]
        public async Task ErrorsAsync()
        {
            // Get a connection string to our Azure Storage account.
            string connectionString = ConnectionString;

            // Get a reference to a container named "sample-container" and then create it
            BlobContainerClient container = new BlobContainerClient(connectionString, Randomize("sample-container"));
            await container.CreateAsync();

            try
            {
                // Try to create the container again
                await container.CreateAsync();
            }
            catch (RequestFailedException ex)
                when (ex.ErrorCode == BlobErrorCode.ContainerAlreadyExists)
            {
                // Ignore any errors if the container already exists
            }
            catch (RequestFailedException ex)
            {
                Assert.Fail($"Unexpected error: {ex}");
            }

            // Clean up after the test when we're finished
            await container.DeleteAsync();
        }
    }
}
```

# コンテイナーの作成

こちらで`sample-container`という名前のコンテイナーの作成を行います

```csharp

 // Get a reference to a container named "sample-container" and then create it
BlobContainerClient container = new BlobContainerClient(connectionString, Randomize("sample-container"));

await container.CreateAsync();
```

## ファイルのアップロード

下記でファイルをアップロードします

```csharp
// Get a reference to a blob
BlobClient blob = container.GetBlobClient(Randomize("sample-file"));

// Open the file and upload its data
using (FileStream file = File.OpenRead(path))
{
  await blob.UploadAsync(file);
}
```

そしてファイルがアップロードできているかどうかを確認しています。

```csharp
// Verify we uploaded some content
BlobProperties properties = await blob.GetPropertiesAsync();
Assert.AreEqual(SampleFileContent.Length, properties.ContentLength);
```

## コンテイナーの削除

そしてコンテイナーを削除します（テストなので）

```csharp
// Clean up after the test when we're finished
await container.DeleteAsync();
```

# ファイルをダウンロード

では、次にアップロードしたファイルをダウンロードします。

```csharp
// Download the blob's contents and save it to a file
BlobDownloadInfo download = await blob.DownloadAsync();
using (FileStream file = File.OpenWrite(downloadPath))
{
  await download.Content.CopyToAsync(file);
}
```

ダウンロードしたコンテンツが正しいものか下記で確認します。

```csharp
// Verify the contents
Assert.AreEqual(SampleFileContent, File.ReadAllText(downloadPath));
```

ファイルの一覧

最後にファイルの一覧を参照します

```csharp
List<string> names = new List<string>();
await foreach (BlobItem blob in container.GetBlobsAsync())
{
  names.Add(blob.Name);
}
```

ここではわかりやすいように`List<string>`に対してloopを回していますが、`GetBlibAsync()`でリストを取得することができます。

# 次

今回は主にサンプルコードのレビューとなりましたが、次回は（未定）Containerの設定管理に関してみていきたいと思います。

フォームからファイルをアップロードする具体的な方法（コード）はこちらを参照ください。
https://qiita.com/syantien/items/a816d4d02b0bd8d6a06d

# 参照

サンプルコード
https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/samples/Sample01b_HelloWorldAsync.cs

クイックスタート
https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-dotnet