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
今回やることは以下の通り
- Visual Studio で作成した MVC アプリケーションから Blob を操作できる環境を構築する
- 実際にデプロイしたアプリケーションでデータ登録/参照などを実施する
Visual Studio で作成した MVC アプリケーションから Blob を操作できる環境を構築する
Docs に書いてある方法は以下の通り。
- Visual Studio にて、新しいプロジェクトの作成から ASP.NET Web アプリケーション (.NET Framework)を選択する。
- 作成ダイアログで、Web アプリケーション (モデル ビュー コントローラー) を選択する
- ソリューションを右クリックから、追加>接続済みのサービスを選択
- 接続済みのサービスを選択すると、Visual Studio によって Azure Storage 用の NuGet パッケージと appsettings.json へのストレージ接続文字列がインストールされます。
- 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>© @DateTime.Now.Year - マイ ASP.NET アプリケーション</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>