Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存

Grant_Allen發表於2020-09-04

一,引言

  上一篇文章,我們介紹到在實際專案中系統會產生大量的日誌檔案,使用者上傳的頭像等等,同時也介紹到可以使用Azure Blob Storage 來儲存專案中的一些日誌檔案,使用者頭像,使用者視訊等等。這個時候,有人就會問到,那我大概明白Blob可以存放什麼型別的資料了,這個時候就有人問一些問題了

  1,什麼是Blob?

  答 Azure Blob 儲存是非結構化的,它可以儲存的資料型別是沒有任何限制的。如,pdf文件,json檔案,視訊,txt檔案等。我們常見的型別的檔案,它統統可以進行儲存。但是 Blob 不適合需要經常查詢的結構化資料, 比如說專案中使用的,它們具有比記憶體和本地磁碟更高的延遲,並且沒有可讓資料庫高效執行查詢的索引功能。但是,blob經常用與資料庫一起用於儲存不可查詢的的資料,例如使用者頭像儲存在Blob中,資料庫中儲存對應使用者頭像的Blob名稱或URL(來自微軟官方解釋

  其實用可以這麼說,如果專案中有對於的圖片資源,視訊資源,檔案等資源,我們就可以考慮到將這些資料都儲存在Azure Blob中。今天在文章的後半段我們將通過一個簡單的 .NET Core Web 程式去操作 Blob 儲存物件。 

二,正文

開始之前我們看看 Blob 的型別

  1,block blob(塊 blob):由不同大小的塊構成,在寫入到塊 blob 時,需要將資料上傳到塊並將其提交到 blob。

  2,append blob(追加 blob):是專用的塊 blob,它僅支援追加新資料,追加操作非常高效。 追加 blob 非常適用於儲存日誌或寫入流資料等方案。

  3,page blob(頁 blob):專用於涉及隨機存取讀寫的方案。 頁 blob 用於儲存 Azure 虛擬機器所使用的虛擬硬碟 (VHD) 檔案,但它們非常適用於任何涉及到隨機存取的方案。

 今天我們演示的是 block blob類似,實際專案中,我們是如何進行操作的

1,Azure Portal 上進行建立 blob 資料

找到之前建立好的 “cnbateblogaccount” Storage Account,點選圖中圈起來的 “Containers”,進行建立容器

點選 “ + Container ”,進行建立容器

注意:這裡的容器,我們可以理解為用來儲存物件的容器

Name:“picturecontainer”

Public access level 選擇:“Private(no anonymous access)”(私有的,不允許匿名訪問)

點選 “Create"

建立完成後,我們就可以在當前容器頁面看到自己建立的 ”picturecontainer“ 資訊。

我們點選容器進入,嘗試在上傳一張圖片進行測試

點選 “Select a file” 進行選擇

選擇 “background.jpg”,點選 "開啟"

勾選 “Overwrite if file already exist”(如果檔案儲存,就覆蓋)

點選 “Upload” 進行上傳

我們可以看到上傳的圖片檔案,並且它的 Blob 型別是 “block blob”

同時,我們可以還有在Portal 上進行預覽,編輯操作。

ok,上述操作我們是在Azure Portal 上進行操作的。接下來我們通過程式碼進行 blob 的增刪查

2,通過ASP.NET Core Web 專案進行Blob資料操作

vs2019 新建 Web 專案

2.1,首先得安裝 Azure.Storage相關的包

NuGet:Azure.Storage.Blobs

我們建立  BlobExplorerController 控制器

[HttpGet("{BlobName}")]
public async Task<IActionResult> GetBlob(string blobName)
{
     var data = await _blobService.GetBlobAsync(blobName);
     return File(data.Content, data.ContentType);
}

2.2,建立 IBlobService 介面,和 BlobService 實現類,新增獲取 Blob 的介面定義和具體實現方法

Task<BlobInfo> GetBlobAsync(string name);
#region 01,獲取Blob,根據blob名稱+async Task<BlobInfo> GetBlobAsync(string name)
/// <summary>
/// 獲取Blob,根據blob名稱
/// </summary>
/// <param name="name">blob名稱</param>
/// <returns></returns>
public async Task<Azure.Storage.Models.BlobInfo> GetBlobAsync(string name)
{
   var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");

   var blobClient = containerClient.GetBlobClient(name);
   var blobDownLoadInfo = await blobClient.DownloadAsync();
   return new Azure.Storage.Models.BlobInfo(blobDownLoadInfo.Value.Content, blobDownLoadInfo.Value.ContentType);
 }
 #endregion

建立 BlobInfo 返回實體資訊

public class BlobInfo
    {
        public BlobInfo(Stream content, string contentType)
        {
            this.Content = content;
            this.ContentType = contentType;
        }
        public Stream Content { get; set; }

        public string ContentType { get; set; }
    }

2.3 配置連結字串

Azure Portal 中找到建立的 “cnbateaccount” 的Azure Blob Atorage,點選 “ Setting=> Access key”

複製圖中的 “Connection string” 

將資料庫連結字串配置在專案的 appsettings 配置檔案中

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "AzureBlobStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=cnbateblogaccount;AccountKey=FU01h022mn1JjONp+ta0DAXOO7ThK3dxxxxxxxxxxxxxxxxx891n9nycsTLGZF83nJpGvTIZvO5VCVxxxxxx0wndOOQ==;EndpointSuffix=core.windows.net"
}

2.4,注入 BlobService,BlobServiceClient

services.AddSingleton(x => new BlobServiceClient(Configuration.GetValue<string("AzureBlobStorageConnectionString")));

services.AddSingleton<IBlobSergvice, BlobService>();

Ok,我們啟動專案進行測試

postman 中輸入 :localhost:9001/Blobs/background.jpg,效果如下圖所示:

瀏覽器訪問:http://localhost:9001/Blobs/background.jpg,效果如下圖所示: 

ok,成功,成功獲取到之前在 Portal 上傳的圖片

2.5 ,完善對 Blob 資料的新增,刪除操作

BlobExplorerController 完整程式碼

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
 1 [Route("Blobs")]
 2     public class BlobExplorerController : Controller
 3     {
 4         private readonly IBlobSergvice _blobService;
 5 
 6         public BlobExplorerController(IBlobSergvice blobService)
 7         {
 8             this._blobService = blobService;
 9         }
10 
11         [HttpGet("{BlobName}")]
12         public async Task<IActionResult> GetBlob(string blobName)
13         {
14             var data = await _blobService.GetBlobAsync(blobName);
15             return File(data.Content, data.ContentType);
16         }
17 
18         [HttpGet("BlobsName")]
19         public async Task<IActionResult> ListBlobsName()
20         {
21             return Ok(await _blobService.ListBlobsNameAsync());
22         }
23 
24         [HttpPost("UploadFile")]
25         public async Task<IActionResult> UpLoadFile([FromBody] UploadFileRequest request)
26         {
27             await _blobService.UploadFileBlobAsync(request.FilePath, request.FileName);
28             return Ok();
29         }
30 
31         [HttpPost("UploadContent")]
32         public async Task<IActionResult> UploadContent([FromBody] UpLoadContentRequest request)
33         {
34             await _blobService.UploadContentBlobAsync(request.Content, request.FileName);
35             return Ok();
36         }
37 
38         [HttpDelete("{BlobName}")]
39         public async Task<IActionResult> DaleteFile(string blobName)
40         {
41             await _blobService.DeleteBlobAsync(blobName);
42             return Ok();
43         }
44     }
BlobExplorerController

IBlobSergvice 介面類

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
public interface IBlobSergvice
    {
        Task<BlobInfo> GetBlobAsync(string name);

        Task<IEnumerable<string>> ListBlobsNameAsync();

        Task UploadFileBlobAsync(string filePath, string filename);

        Task UploadContentBlobAsync(string content, string filename);

        Task DeleteBlobAsync(string blobName);

    }
IBlobSergvice

BlobService 實現類

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
 1 public class BlobService : IBlobSergvice
 2     {
 3         private readonly BlobServiceClient _blobServiceClient;
 4 
 5         public BlobService(BlobServiceClient blobServiceClient)
 6         {
 7             this._blobServiceClient = blobServiceClient;
 8         }
 9 
10         #region 01,獲取Blob,根據blob名稱+async Task<BlobInfo> GetBlobAsync(string name)
11         /// <summary>
12         /// 獲取Blob,根據blob名稱
13         /// </summary>
14         /// <param name="name">blob名稱</param>
15         /// <returns></returns>
16         public async Task<Azure.Storage.Models.BlobInfo> GetBlobAsync(string name)
17         {
18             var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
19 
20             var blobClient = containerClient.GetBlobClient(name);
21             var blobDownLoadInfo = await blobClient.DownloadAsync();
22             return new Azure.Storage.Models.BlobInfo(blobDownLoadInfo.Value.Content, blobDownLoadInfo.Value.ContentType);
23         }
24         #endregion
25 
26         #region 02,獲取所有Blob名稱+async Task<IEnumerable<string>> ListBlobsNameAsync()
27         /// <summary>
28         /// 獲取所有Blob名稱
29         /// </summary>
30         /// <returns></returns>
31         public async Task<IEnumerable<string>> ListBlobsNameAsync()
32         {
33             var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
34             var items = new List<string>();
35 
36             await foreach (var blobItem in containerClient.GetBlobsAsync())
37             {
38                 items.Add(blobItem.Name);
39             }
40             return items;
41         }
42         #endregion
43 
44         #region 03,上傳圖片流,根據檔案路徑和檔名稱+async Task UploadFileBlobAsync(string filePath, string filename)
45         /// <summary>
46         /// 上傳圖片流,根據檔案路徑和檔名稱
47         /// </summary>
48         /// <param name="filePath">檔案路徑</param>
49         /// <param name="filename">檔名稱</param>
50         /// <returns></returns>
51         public async Task UploadFileBlobAsync(string filePath, string filename)
52         {
53             var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
54             var blobClient = containerClient.GetBlobClient(filename);
55             await blobClient.UploadAsync(filePath, new BlobHttpHeaders { ContentType = filePath.GetContentType() });
56         }
57         #endregion
58 
59         #region 04,上傳檔案流,根據檔案內容和檔名稱+async Task UploadContentBlobAsync(string content, string filename)
60         /// <summary>
61         /// 上傳檔案流,根據檔案內容和檔名稱
62         /// </summary>
63         /// <param name="content">檔案內容</param>
64         /// <param name="filename">檔名稱</param>
65         /// <returns></returns>
66         public async Task UploadContentBlobAsync(string content, string filename)
67         {
68             var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
69             var blobClient = containerClient.GetBlobClient(filename);
70             var bytes = Encoding.UTF8.GetBytes(content);
71             await using var memoryStream = new MemoryStream(bytes);
72             await blobClient.UploadAsync(memoryStream, new BlobHttpHeaders() { ContentType = filename.GetContentType() });
73         }
74         #endregion
75 
76         #region 05,刪除Blob+async Task DeleteBlobAsync(string blobName)
77         /// <summary>
78         /// 刪除Blob
79         /// </summary>
80         /// <param name="blobName">blob名稱</param>
81         /// <returns></returns>
82         public async Task DeleteBlobAsync(string blobName)
83         {
84             var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
85             var blobClient = containerClient.GetBlobClient(blobName);
86             await blobClient.DeleteIfExistsAsync();
87         } 
88         #endregion
89     }
BlobService

UpLoadContentRequest

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
 1 public class UpLoadContentRequest
 2     {
 3         /// <summary>
 4         /// 檔案內容
 5         /// </summary>
 6         public string Content { get; set; }
 7 
 8         /// <summary>
 9         /// 檔名稱
10         /// </summary>
11         public string FileName { get; set; }
12     }
UpLoadContentRequest

UploadFileRequest

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
 1 public class UploadFileRequest
 2     {
 3         /// <summary>
 4         /// 檔案路徑
 5         /// </summary>
 6         public string FilePath { get; set; }
 7 
 8         /// <summary>
 9         /// 檔名稱
10         /// </summary>
11         public string FileName { get; set; }
12     }
UploadFileRequest

FileExtensions 擴充套件類

Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
 1 public static class FileExtensions
 2     {
 3         private static readonly FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
 4 
 5         public static string GetContentType(this string fileName)
 6         {
 7             if (!provider.TryGetContentType(fileName, out var contentType))
 8             {
 9                 contentType = "application/octet-stream";
10             }
11             return contentType;
12         }
13     }
FileExtensions

目前我們分別新增了 上傳圖片介面,上傳檔案介面,刪除檔案介面

我們分別在 postman 中進行測試

(1)上傳圖片

FilePath(檔案路徑):”C:\\Users\\admin\\Desktop\\2020904001.jpg“

FileName(檔名稱):”2020904001.jpg“

點選 ”Send“,我們可以看到響應返回狀態碼(Status) ”200 OK“

同時在 Portal 上也可以看到剛剛選擇的 ”20200904001.jpg“ 檔案

 

這裡注意一下,為什麼我們制定檔案的路徑,和名稱就可以上傳檔案,並且可以在瀏覽器中檢視,那是因為我們在上傳檔案中設定檔案的請求頭的原因

private static readonly FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();

        public static string GetContentType(this string fileName)
        {
            if (!provider.TryGetContentType(fileName, out var contentType))
            {
                contentType = "application/octet-stream";
            }
            return contentType;
        }
public async Task UploadFileBlobAsync(string filePath, string filename)
        {
            var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
            var blobClient = containerClient.GetBlobClient(filename);
            await blobClient.UploadAsync(filePath, new BlobHttpHeaders { ContentType = filePath.GetContentType() });
        }

(2)上傳json檔案

Content:"{ \"Name\" : \"zhangsan\", \"Reamrk\" : \"This is work!!!\" }"

FileName:”log.json“

點選 ”Send“,上傳 Json 檔案

我們繼續在 Portal 上進行檢視上傳的 json 檔案

(3)檢視 Blob 資訊

 

接下來還是刪除 Blob 資料的操作,我這裡就不做演示了,大家可以自己呼叫介面進行測試

好的,那今天的內容就先到此結束,今天的目的只是通過簡單的demo程式碼去演示如果操作 Azure Blob 資料,簡單的跑跑程式碼,在.NET Core 中的demo程式碼是怎麼去寫的,具體的Azure.Storage 類中的方法,引數等今天的內容暫時不去解釋。

鼓掌,撒花?????

三,結尾

今天的文章大概介紹了在 Portal 上如何上傳 blob 圖片檔案,以及寫了一個簡單的 .NET Core demo 程式,通過程式碼我們我們去控制 Blob 資料的增刪改查,下一篇繼續介紹 Azure Storage 在程式碼中的操作,也著重講一下Azure.Storage 中的類,以及方法的具體呼叫和說明。

github:https://github.com/yunqian44/Azure.Storage.git

作者:Allen 

版權:轉載請在文章明顯位置註明作者及出處。如發現錯誤,歡迎批評指正。

相關文章