一,引言
上一篇文章,我們介紹到在實際項目中系統會產生大量的日志文件,用戶上傳的頭像等等,同時也介紹到可以使用Azure Blob Storage 來存儲項目中的一些日志文件,用戶頭像,用戶視頻等等。這個時候,有人就會問到,那我大概明白Blob可以存放什么類型的數據了,這個時候就有人問一些問題了
1,什么是Blob?
答 Azure Blob 存儲是非結構化的,它可以保存的數據類型是沒有任何限制的。如,pdf文檔,json文件,視頻,txt文件等。我們常見的類型的文件,它統統可以進行存儲。但是 Blob 不適合需要經常查詢的結構化數據, 比如說項目中使用的,它們具有比內存和本地磁盤更高的延遲,並且沒有可讓數據庫高效運行查詢的索引功能。但是,blob經常用與數據庫一起用於存儲不可查詢的的數據,例如用戶頭像存儲在Blob中,數據庫中保存對應用戶頭像的Blob名稱或URL(來自微軟官方解釋)
其實用可以這么說,如果項目中有對於的圖片資源,視頻資源,文件等資源,我們就可以考慮到將這些數據都存儲在Azure Blob中。今天在文章的后半段我們將通過一個簡單的 .NET Core Web 程序去操作 Blob 存儲對象。
--------------------我是分割線--------------------
Azure Blob Storage 存儲系列:
2,Azure Storage 系列(二) .NET Core Web 項目中操作 Blob 存儲
3,Azure Storage 系列(三)Blob 參數設置說明
4,Azure Storage 系列(四)在.Net 上使用Table Storage
5,Azure Storage 系列(五)通過Azure.Cosmos.Table 類庫在.Net 上使用 Table Storage
6,Azure Storage 系列(六)使用Azure Queue Storage
二,正文
開始之前我們看看 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 完整代碼

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 }
IBlobSergvice 接口類

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); }
BlobService 實現類

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 }
UpLoadContentRequest

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 }
UploadFileRequest

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 }
FileExtensions 擴展類

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 }
目前我們分別添加了 上傳圖片接口,上傳文件接口,刪除文件接口
我們分別在 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
版權:轉載請在文章明顯位置注明作者及出處。如發現錯誤,歡迎批評指正。