Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储

一,引言

  上一篇文章,我们介绍到在实际项目中系统会产生大量的日志文件,用户上传的头像等等,同时也介绍到可以使用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 存储系列:

1,Azure Storage 系列(一)入门简介

2,Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储

3,Azure Storage 系列(三)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”,进行创建容器

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第1张图片

点击 “ + Container ”,进行创建容器

注意:这里的容器,我们可以理解为用来存储对象的容器

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第2张图片

Name:“picturecontainer”

Public access level 选择:“Private(no anonymous access)”(私有的,不允许匿名访问)

点击 “Create"

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第3张图片

创建完成后,我们就可以在当前容器页面看到自己创建的 ”picturecontainer“ 信息。

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第4张图片

我们点击容器进入,尝试在上传一张图片进行测试

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第5张图片

点击 “Select a file” 进行选择

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第6张图片

选择 “background.jpg”,点击 "打开"

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第7张图片

勾选 “Overwrite if file already exist”(如果文件存储,就覆盖)

点击 “Upload” 进行上传

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第8张图片

我们可以看到上传的图片文件,并且它的 Blob 类型是 “block blob”

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第9张图片

同时,我们可以还有在Portal 上进行预览,编辑操作。

ok,上述操作我们是在Azure Portal 上进行操作的。接下来我们通过代码进行 blob 的增删查

2,通过ASP.NET Core Web 项目进行Blob数据操作

vs2019 新建 Web 项目

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第10张图片

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第11张图片

2.1,首先得安装 Azure.Storage相关的包

NuGet:Azure.Storage.Blobs

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第12张图片

我们创建  BlobExplorerController 控制器

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

2.2,创建 IBlobService 接口,和 BlobService 实现类,新增获取 Blob 的接口定义和具体实现方法

Task GetBlobAsync(string name);
#region 01,获取Blob,根据blob名称+async Task GetBlobAsync(string name)
/// 
/// 获取Blob,根据blob名称
/// 
/// blob名称
/// 
public async Task 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” 

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第13张图片

将数据库链接字符串配置在项目的 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();

Ok,我们启动项目进行测试

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

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第14张图片

浏览器访问: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 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 ListBlobsName()
20         {
21             return Ok(await _blobService.ListBlobsNameAsync());
22         }
23 
24         [HttpPost("UploadFile")]
25         public async Task 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 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 DaleteFile(string blobName)
40         {
41             await _blobService.DeleteBlobAsync(blobName);
42             return Ok();
43         }
44     }
BlobExplorerController

IBlobSergvice 接口类

public interface IBlobSergvice
    {
        Task GetBlobAsync(string name);

        Taskstring>> ListBlobsNameAsync();

        Task UploadFileBlobAsync(string filePath, string filename);

        Task UploadContentBlobAsync(string content, string filename);

        Task DeleteBlobAsync(string blobName);

    }
IBlobSergvice

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 GetBlobAsync(string name)
11         /// 
12         /// 获取Blob,根据blob名称
13         /// 
14         /// blob名称
15         /// 
16         public async Task 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> ListBlobsNameAsync()
27         /// 
28         /// 获取所有Blob名称
29         /// 
30         /// 
31         public async Taskstring>> 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         /// 
46         /// 上传图片流,根据文件路径和文件名称
47         /// 
48         /// 文件路径
49         /// 文件名称
50         /// 
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         /// 
61         /// 上传文件流,根据文件内容和文件名称
62         /// 
63         /// 文件内容
64         /// 文件名称
65         /// 
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         /// 
78         /// 删除Blob
79         /// 
80         /// blob名称
81         /// 
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

 1 public class UpLoadContentRequest
 2     {
 3         /// 
 4         /// 文件内容
 5         /// 
 6         public string Content { get; set; }
 7 
 8         /// 
 9         /// 文件名称
10         /// 
11         public string FileName { get; set; }
12     }
UpLoadContentRequest

UploadFileRequest

 1 public class UploadFileRequest
 2     {
 3         /// 
 4         /// 文件路径
 5         /// 
 6         public string FilePath { get; set; }
 7 
 8         /// 
 9         /// 文件名称
10         /// 
11         public string FileName { get; set; }
12     }
UploadFileRequest

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

目前我们分别添加了 上传图片接口,上传文件接口,删除文件接口

我们分别在 postman 中进行测试

(1)上传图片

FilePath(文件路径):”C:\\Users\\admin\\Desktop\\2020904001.jpg“

FileName(文件名称):”2020904001.jpg“

点击 ”Send“,我们可以看到响应返回状态码(Status) ”200 OK“

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第15张图片

同时在 Portal 上也可以看到刚刚选择的 ”20200904001.jpg“ 文件

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第16张图片

 Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第17张图片

这里注意一下,为什么我们制定文件的路径,和名称就可以上传文件,并且可以在浏览器中查看,那是因为我们在上传文件中设置文件的请求头的原因

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 文件

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第18张图片

我们继续在 Portal 上进行查看上传的 json 文件

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第19张图片

Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第20张图片

(3)查看 Blob 信息

 Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储_第21张图片

接下来还是删除 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 

版权:转载请在文章明显位置注明作者及出处。如发现错误,欢迎批评指正。

你可能感兴趣的:(Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储)