LoginSignup
3
2

More than 3 years have passed since last update.

ASP.NET で Azure Blob Storage を操作してみる

Posted at

Visual Studio で BlobStorage を扱う Web アプリケーションを作成する

BlobStorgae の扱いは Cognitive Services や Data/AI を扱う上で非常に便利になってくるみたいです。
加えて Functions などのサーバーレスコンピューティングとの連携も非常にスムーズ。
これまであまり BlobStorage に触れてこなかったのですが、今回は整理も兼ねて基礎的な部分を整理しておきたいと思います。

参考:Azure Blob Storage と Visual Studio 接続済みサービスの概要 (ASP.NET)
https://docs.microsoft.com/ja-jp/azure/visual-studio/vs-storage-aspnet-getting-started-blobs

今回やることは以下の通り
1. Visual Studio で作成した MVC アプリケーションから Blob を操作できる環境を構築する
2. 実際にデプロイしたアプリケーションでデータ登録/参照などを実施する

Visual Studio で作成した MVC アプリケーションから Blob を操作できる環境を構築する

Docs に書いてある方法は以下の通り。
1. Visual Studio にて、新しいプロジェクトの作成から ASP.NET Web アプリケーション (.NET Framework)を選択する。
2. 作成ダイアログで、Web アプリケーション (モデル ビュー コントローラー) を選択する
3. ソリューションを右クリックから、追加>接続済みのサービスを選択
4. 接続済みのサービスを選択すると、Visual Studio によって Azure Storage 用の NuGet パッケージと appsettings.json へのストレージ接続文字列がインストールされます。
5. MVC コントローラーを作成する (BlobsController という名前を付ける)

ここまでは普通に進むのだけど、ここから先の Storage Connection String を入力するのが、Docs だと分かりにくい!!
Docs の記載は以下の通り。

"CloudBlobContainer を返す GetCloudBlobContainer と呼ばれるメソッドを追加します。 必ず _AzureStorageConnectionString を Web.config 内の実際のキーの名前に置き換えてください。"

記載方法的に、Web.config の中の文字をそのまま使えばよいのだが、それよりも、「Connection String」の値をそのまま_AzureStorageConnectionString に置き換えれば良いという話だった。

Visual Studio から Storage Services を接続すると、必要な NugetPackage と web.config は自動的に更新されるのだが、いちいちそれをコピペするのはめんどくさい、、、。なのでここは Azure Portal から直接貼った方が楽かもです。

ここまでくれば、あとはデプロイすればローカル環境から Blob に接続し、新しいコンテナーを作成することができます。

実際にデプロイしたアプリケーションでデータ登録/参照などを実施する

UplodadBlob() メソッドの中のOnroadの部分は任意のファイルパスに変えなくてはいけない。

using (var fileStream = System.IO.File.OpenRead(@"<ここのPath!!>"))

あとは基本 Docs 通りに進めば良いが、いまいちど .NET での 参照/作成/アップロード/リスト/ダウンロード/デリートのメソッド詳細について纏めておく・

① 接続 GetCloudBlobContainer() メソッド

private CloudBlobContainer GetCloudBlobContainer()
{
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            CloudConfigurationManager.GetSetting("<storageaccountname>_AzureStorageConnectionString"));
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobClient.GetContainerReference("test-blob-container");
    return container;
}

② 作成 CreateBlobContiner() メソッド

public ActionResult CreateBlobContainer()
{
    CloudBlobContainer container = GetCloudBlobContainer();
    ViewBag.Success = container.CreateIfNotExists();
    ViewBag.BlobContainerName = container.Name;

    return View();
}

③ アップロード Upload() メソッド

public string UploadBlob()
{
    CloudBlobContainer container = GetCloudBlobContainer();
    CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
    using (var fileStream = System.IO.File.OpenRead(@"<任意のパス>"))
    {
        blob.UploadFromStream(fileStream);
    }
    return "success!";
}

④リスト ListBlobs() メソッド

public ActionResult ListBlobs()
{
    CloudBlobContainer container = GetCloudBlobContainer();
    List<string> blobs = new List<string>();
    foreach (IListBlobItem item in container.ListBlobs(useFlatBlobListing: true))
    {
        if (item.GetType() == typeof(CloudBlockBlob))
        {
            CloudBlockBlob blob = (CloudBlockBlob)item;
            blobs.Add(blob.Name);
        }
        else if (item.GetType() == typeof(CloudPageBlob))
        {
            CloudPageBlob blob = (CloudPageBlob)item;
            blobs.Add(blob.Name);
        }
        else if (item.GetType() == typeof(CloudBlobDirectory))
        {
            CloudBlobDirectory dir = (CloudBlobDirectory)item;
            blobs.Add(dir.Uri.ToString());
        }
    }

    return View(blobs);
}

⑤ ダウンロード Download() メソッド

public string DownloadBlob()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
            using (var fileStream = System.IO.File.OpenWrite(@"C:\Users\komiyasa\source\repos\sample.txt"))
            {
                blob.DownloadToStream(fileStream);
            }
            return "success!";
        }

⑥ 削除 DeleteBlob() メソッド

public string DeleteBlob()
{
    CloudBlobContainer container = GetCloudBlobContainer();
    CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
    blob.Delete();
    return "success!";
}

最終的に変更したファイル

・BlobController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.Azure;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

namespace WebApplication1.Controllers
{
    public class BlobsController : Controller
    {
        // GET: Blobs
        public ActionResult Index()
        {
            return View();
        }

        private CloudBlobContainer GetCloudBlobContainer()
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
                    CloudConfigurationManager.GetSetting("<<ここに Connection String を入れる>>"));
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = blobClient.GetContainerReference("test-blob-container");
            return container;
        }

        public ActionResult CreateBlobContainer()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            ViewBag.Success = container.CreateIfNotExists();
            ViewBag.BlobContainerName = container.Name;

            return View();
        }

        public string UploadBlob()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
            using (var fileStream = System.IO.File.OpenRead(@"C:\Users\komiyasa\source\repos\sample.txt"))
            {
                blob.UploadFromStream(fileStream);
            }
            return "success!";
        }

        public ActionResult ListBlobs()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            List<string> blobs = new List<string>();
            foreach (IListBlobItem item in container.ListBlobs(useFlatBlobListing: true))
            {
                if (item.GetType() == typeof(CloudBlockBlob))
                {
                    CloudBlockBlob blob = (CloudBlockBlob)item;
                    blobs.Add(blob.Name);
                }
                else if (item.GetType() == typeof(CloudPageBlob))
                {
                    CloudPageBlob blob = (CloudPageBlob)item;
                    blobs.Add(blob.Name);
                }
                else if (item.GetType() == typeof(CloudBlobDirectory))
                {
                    CloudBlobDirectory dir = (CloudBlobDirectory)item;
                    blobs.Add(dir.Uri.ToString());
                }
            }

            return View(blobs);
        }

        public string DownloadBlob()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
            using (var fileStream = System.IO.File.OpenWrite(@"C:\Users\komiyasa\source\repos\sample.txt"))
            {
                blob.DownloadToStream(fileStream);
            }
            return "success!";
        }

        public string DeleteBlob()
        {
            CloudBlobContainer container = GetCloudBlobContainer();
            CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
            blob.Delete();
            return "success!";
        }
    }
}

・Views/Shared/_Layout.schtml

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("アプリケーション名", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("ホーム", "Index", "Home")</li>
                    <li>@Html.ActionLink("詳細", "About", "Home")</li>
                    <li>@Html.ActionLink("問い合わせ", "Contact", "Home")</li>
                    <li>@Html.ActionLink("Create blob container", "CreateBlobContainer", "Blobs")</li>
                    <li>@Html.ActionLink("Upload blob", "UploadBlob", "Blobs")</li>
                    <li>@Html.ActionLink("List blobs", "ListBlobs", "Blobs")</li>
                    <li>@Html.ActionLink("Download blob", "DownloadBlob", "Blobs")</li>
                    <li>@Html.ActionLink("Delete blob", "DeleteBlob", "Blobs")</li>


                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - マイ ASP.NET アプリケーション</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

<成功イメージ>
image.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2