一,引言

  上一篇文章有介绍到什么是 SeverLess ,ServerLess 都有哪些特点,以及多云环境下 ServerLess 都有哪些解决方案。在这众多解决方案中就包括 Function App(Azure 下的ServerLess),今天我们结合之前所讲的 Azure Functions 以及 Azure Blob Storage 的相关知识,从实践出发,再次回顾之前的知识点,以下是构想的基础资源架构图

--------------------Azure Functions 系列--------------------

1,使用 Visual Studio 开发、测试和部署 Azure Functions(一)开发

2,使用 Visual Studio 开发、测试和部署 Azure Functions(二)测试,部署

3,使用Azure Functions 在web 应用中启用自动更新(一)分析基于轮询的 Web 应用的限制

4,Azure Functions(一)什么是 ServerLess

5,Azure Functions(二)集成 Azure Blob Storage 存储文件

二,正文

1,创建 Function App

Azure Portal,点击“Create a resource”,搜索框中输入 “Function App”。

点击 “Create”,创建 Function App

输入相关参数:

Resource Group 选择创建新的资源组:“Web_Test_Functions_RG”

Function App name:“cnbateblogweb”

Publicsh 发布方式:Code(代码)

Runtime stack 选择:“.NET”

Version:“3.1”

Region 选择:“East  Asia”

点击 “Next:Hosting” 设置承载

接下来 “Hosting” 相关参数

Storage:当我们在创建函数应用时,必须创建或链接到支持的Blob,Queue,Table Storage 的常规用途的 Azure 存储账号

Storage Account 选择创建新的:cnbatestorageaccount

Operation system 选择:“Windows”

Plan 选择:Consumption(ServerLess) 消耗(无服务器)

点击 “Next:Monitoring >” 设置监视信息

接下来我们需要自身的需要 选择是否开启 Application Insights(用于在应用程序中提供详细的可观测性)

Enable Application Insights:“Yes”

Application Insights 选择创建新的:“cnbateblogweb”

点击 “Review + create”,创建预览。

预校验完成后,点击 “Create” 进行创建。

稍等片刻,我们回到 “Web_Test_Functions_RG” 这个资源组可以查看到我们创建好的资源

最后,我们需要创建用于保存图片的 Blob Container

选择 “Blob service =》Container”,点击箭头所指的 “+ Container”

输入创建新的容器的相关参数:

Name:“picturecontainer”

Public access level 选择默认:“Private(no anonymous access)”

点击 “Create”

创建完成后,就可以在当前页面上看到 “picturecontainer” 的 Blob Container

2,Azure FunctionApp 添加对 Blob Storage 的使用方法

2.1,添加相关 Nuget  依赖包引用

使用程序包管理器控制台进行安装

Install-Package Azure.Storage.Blobs -Version 12.8.0
Install-Package Microsoft.AspNetCore.StaticFiles -Version 2.2.0
Install-Package Microsoft.Azure.Functions.Extensions -Version 1.1.0
Install-Package Microsoft.Extensions.DependencyInjection -Version 5.0.1
Install-Package Microsoft.NET.Sdk.Functions -Version 3.0.11

这里要注意的是 "Microsoft.Extensions.DependencyInjection"、"Microsoft.NET.Sdk.Functions"、"Microsoft.Azure.Functions.Extensions" ,主要是想在 Azure Functions 中使用一俩注入(DI)

大家可以自行参考 Use dependency injection in .NET Azure Functions

2.2,IBlobService 接口方法定义,BlobService 具体实现和 Http触发器

1 public interface IBlobService
2 {
3 Task UploadImagesBlobAsync(string filePath, string filename);
4
5 Task UploadFileBlobAsync(string filePath, string filename);
6
7 Task UploadContentBlobAsync(string content, string filename);
8 }

IBlobService.cs

 1 public class BlobService : IBlobService
2 {
3 private readonly BlobServiceClient _blobServiceClient;
4
5 public BlobService(BlobServiceClient blobServiceClient)
6 {
7 this._blobServiceClient = blobServiceClient;
8 }
9
10 #region 02,抓取网络图片,根据图片URL和图片名称+async Task UploadFileBlobAsync(string filePath, string filename)
11 /// <summary>
12 /// 上传图片流,根据图片URL和图片名称
13 /// </summary>
14 /// <param name="filePath">图片URL</param>
15 /// <param name="filename">图片名称</param>
16 /// <returns></returns>
17 public async Task UploadImagesBlobAsync(string filePath, string filename)
18 {
19 var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
20 var blobClient = containerClient.GetBlobClient(filename);
21
22 #region 获取图片流
23 var response = FeatchPictureClient.GetWebResponse(filePath);
24 var bytes = FeatchPictureClient.GetResponseStream(response);
25 await using var memoryStream = new MemoryStream(bytes);
26
27 //上传图片流
28 await blobClient.UploadAsync(memoryStream, new BlobHttpHeaders() { ContentType = filename.GetContentType() });
29 #endregion
30 }
31 #endregion
32
33 #region 03,上传图片,根据文件路径和文件名称+async Task UploadFileBlobAsync(string filePath, string filename)
34 /// <summary>
35 /// 上传图片流,根据文件路径和文件名称
36 /// </summary>
37 /// <param name="filePath">文件路径</param>
38 /// <param name="filename">文件名称</param>
39 /// <returns></returns>
40 public async Task UploadFileBlobAsync(string filePath, string filename)
41 {
42 var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
43 var blobClient = containerClient.GetBlobClient(filename);
44 await blobClient.UploadAsync(filePath, new BlobHttpHeaders { ContentType = filePath.GetContentType() });
45 }
46 #endregion
47
48 #region 04,上传文件内容,根据文件内容和文件名称+async Task UploadContentBlobAsync(string content, string filename)
49 /// <summary>
50 /// 上传文件流,根据文件内容和文件名称
51 /// </summary>
52 /// <param name="content">文件内容</param>
53 /// <param name="filename">文件名称</param>
54 /// <returns></returns>
55 public async Task UploadContentBlobAsync(string content, string filename)
56 {
57 var containerClient = _blobServiceClient.GetBlobContainerClient("picturecontainer");
58 var blobClient = containerClient.GetBlobClient(filename);
59 var bytes = Encoding.UTF8.GetBytes(content);
60 await using var memoryStream = new MemoryStream(bytes);
61 await blobClient.UploadAsync(memoryStream, new BlobHttpHeaders() { ContentType = filename.GetContentType() });
62 }
63 #endregion
64
65 }

BlobService.cs

 1 public class UpLoadTrigger
2 {
3 private readonly IBlobService _blobSergvice;
4
5 public UpLoadTrigger(IBlobService blobSergvice)
6 {
7 _blobSergvice = blobSergvice;
8 }
9
10 [FunctionName("UpLoadTrigger")]
11 public async Task<IActionResult> Run(
12 [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] BlobViewModel req,
13 ILogger log)
14 {
15 log.LogInformation("C# HTTP trigger function processed a request.");
16
17 await _blobSergvice.UploadImagesBlobAsync(req.FilePath, req.FileName);
18 return new OkObjectResult("ok");
19 }
20 }

UpLoadTrigger.cs

2.3,FileExtensions 方法和 FeatchpictureClient 网络请求方法

 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.cs

 1 public class FeatchPictureClient
2 {
3 /// <summary>
4 /// 获取URL响应对象
5 /// </summary>
6 /// <param name="url"></param>
7 /// <returns></returns>
8 public static WebResponse GetWebResponse(string url)
9 {
10 System.Net.HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
11 request.CookieContainer = new CookieContainer();
12 request.KeepAlive = true;
13 WebResponse res = request.GetResponse();
14 return res;
15 }
16
17 public static byte[] GetResponseStream(WebResponse response)
18 {
19 Stream smRes = response.GetResponseStream();
20 byte[] resBuf = new byte[10240];
21 int nReaded = 0;
22 MemoryStream memSm = new MemoryStream();
23 while ((nReaded = smRes.Read(resBuf, 0, 10240)) != 0)
24 {
25 memSm.Write(resBuf, 0, nReaded);
26 }
27 byte[] byResults = memSm.ToArray();
28 memSm.Close();
29 return byResults;
30 }
31 }

FeatchPictureClient.cs

2.4,添加对 BlobService 以及BlobServiceClient 的依赖注入

大家需要注意,我们需要配置Blob Storage 的访问密钥

找到创建 Function App 时一起创建出来的 Storage Account "cnbatestorageaccount "

选择 “Settings =》Access keys”,复制图中圈中的 “Connection string” 粘贴到对应的代码中。

 1 using Azure.Storage.Blobs;
2 using Microsoft.Azure.Functions.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Configuration;
4 using Microsoft.Extensions.DependencyInjection;
5 using System;
6 using System.Collections.Generic;
7 using System.Text;
8 using UploadImages;
9 using UploadImages.Service;
10
11 [assembly: FunctionsStartup(typeof(Startup))]
12
13 namespace UploadImages
14 {
15 public class Startup : FunctionsStartup
16 {
17 //public Startup(IConfiguration configuration)
18 //{
19 // Configuration = configuration;
20 //}
21
22 //public IConfiguration Configuration { get; }
23
24 public override void Configure(IFunctionsHostBuilder builder)
25 {
26 //builder.Services.AddSingleton(x => new BlobServiceClient("storageaccount_connection"));
27 builder.Services.AddSingleton(x => new BlobServiceClient("DefaultEndpointsProtocol=https;AccountName=cnbateblogaccount;AccountKey=f9n+Cm3brR+39SVhNMzzMPj54f6KD7rINi9G2OlxVkk2oUfi3o7ZGdDS8SHkF8H8G5pSmedOOMmOhc95uRNZxA==;EndpointSuffix=core.windows.net"));
28 builder.Services.AddTransient<IBlobService, BlobService>();
29 }
30 }
31 }

Startup.cs

3,测试!触发 HttpTrigger,通过网络请求图片URL,经过处理,将图片存储在Blob Storage

F5运行,可以看到控制中显示 Function App 中的 UpLoadTrigger URLhttp://localhost:7071/api/UpLoadTrigger

Postman 中输入 HttpTrigger 的请求链接,输入 FilePathFileName 两个参数

回到控制台中,我们可以看到 Http 触发器已经成功的处理了请求

同样的,我们也可以在 Blob Container 中找到上传到的网络图片

Bingo!!!大功告成。使用 Vistual Studio 开发,测试Azure Function App 应用完结

三,结尾

  Azure Functions 用来处理很方便,直接将应用级别的项目缩小到方法级别上,在具体的的方法中处理业务,数据。并且 Azure Function 是按照使用付费定价模型:也就是仅仅为运行代码所用的时间而付费,这一点比某云还是好一些。下一篇继续讲解/分享 Azure Function 实例代码。以上也是自己的学习的过程,谢谢各位指点。

参考资料:Azure Functions 简介在 .NET Azure Functions 中使用依赖项注入

作者:Allen

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

Azure Functions(二)集成 Azure Blob Storage 存储文件的更多相关文章

  1. Azure Functions(三)集成 Azure Queue Storage 存储消息

    一,引言 接着上一篇文章继续介绍 Azure Functions,今天我们将尝试绑定 Queue Storage,将消息存储到 Queue 中,并且学会适用于 Azure Functions 的 Az ...

  2. Azure Blob Storage从入门到精通

    今天推荐的是一个系列文章,让读者阅读完成后可以对Azure Blob Storage的开发有一个全面的了解,可谓是从入门到精通. Azure在最初的版本里面就提供了非结构化数据的存储服务,也即Blob ...

  3. 使用 Visual Studio 开发、测试和部署 Azure Functions(一)开发

    1,什么是Azure functions Azure Functions 是 Microsoft Azure 提供的完全托管的 PaaS 服务,用于实现无服务器体系结构. Azure Function ...

  4. 使用Azure Functions & .NET Core快速构建Serverless应用

    Code Repo: https://github.com/Asinta/ServerlessApp_NetconfChina2020 Prerequisites Visual Studio Code ...

  5. 尝鲜一试,Azure静态网站应用服务(Azure Static Web Apps) 免费预览,协同Github自动发布静态SPA

    背景 最近在浏览微软的文档的时候发现,微软喜欢用Hugo这个文档框架,有些技术产品的文档页面就用Hugo来做的,同时搭配Github + Azure Static Web Apps Service这个 ...

  6. Azure Data Factory(五)Blob Storage 密钥管理问题

    一,引言 之前讲解的ADF 集成Azure DevOps 实现CI/CD,在 Releases Pipeline 阶段,我们是将两个 Blob Storage 的链接字符串复制.粘贴到 "O ...

  7. hadoop(四): 本地 hbase 集群配置 Azure Blob Storage

    基于 HDP2.4安装(五):集群及组件安装 创建的hadoop集群,修改默认配置,将hbase 存储配置为 Azure Blob Storage 目录: 简述 配置 验证 FAQ 简述: hadoo ...

  8. Windows Azure入门教学:使用Blob Storage

    对于.net开发人员,这是一个新的领域,但是并不困难.本文将会介绍如何使用Blob Storage.Blob Storage可以看做是云端的文件系统.与桌面操作系统上不同,我们是通过REST API来 ...

  9. Windows Azure入门教学系列 (四):使用Blob Storage

    本文将会介绍如何使用Blob Storage.Blob Storage可以看做是云端的文件系统.与桌面操作系统上不同,我们是通过REST API来进行对文件的操作.有关REST API的详细信息,请参 ...

随机推荐

  1. 大型面试现场:一条update sql执行都经历什么?

    导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 24 篇. 今天我要跟你分享的MySQL话题是:"从一条update sql执行都经历什么开始,发散开一系列的问题,看看你能抗到第几 ...

  2. Spring Cloud Config、Apollo、Nacos配置中心选型及对比

    Spring Cloud Config.Apollo.Nacos配置中心选型及对比 1.Nacos 1.1 Nacos主要提供以下四大功能 2.Spring Cloud Config 3.Apollo ...

  3. CSS中一些重要概念

    在CSS的最后一个博客中,将学习整理一些CSS中的重要概念,对这些重要概念的掌握,将对CSS的认识十分重要. 了解这些概念对深入理解CSS的本质十分重要:(1)包含块containing block ...

  4. 小白搭建WAMP详细教程---php安装与设置

    一.php官网下载php压缩包 到php官网http://www.php.net 下载,有很多版本,我们这里选择7.2.25,具体步骤如下: 二.php的安装 下载后得到如下的压缩包,将压缩包解压到您 ...

  5. 小程序navigateTo和redirectTo跳转的区别与应用

    最近在做小程序的跳转,发现navigateTo的跳转无法满足业务需求,所以特地记录下 业务需求 类似一个淘宝的在订单界面选择地址的功能,从A页面点击跳转到B页面的地址列表页面,B页面可以选择已有的地址 ...

  6. Pytest(10)assert断言

    前言 断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢? 简单来讲就是实际结果和期望结果去对比,符合预期那就测试pass,不符合预期那就测试 failed ...

  7. 牛客练习赛64 D【容斥+背包】

    牛客练习赛64 D.宝石装箱 Description \(n\)颗宝石装进\(n\)个箱子使得每个箱子中都有一颗宝石.第\(i\)颗宝石不能装入第\(a_i\)个箱子.求合法的装箱方案对\(99824 ...

  8. Codeforces Round #627 (Div. 3) C - Frog Jumps(逻辑)

    题意: 有一个每个单元标明移动方向的长为n的序列,每次移动不能超过距离k,问能够从0移动到n+1的k的最小值. 思路: k=最长连续L序列长度+1. #include <bits/stdc++. ...

  9. 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)

    题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...

  10. 表达式目录树插件xLiAd.SqlEx.Core

    表达式目录树使用时 引用xLiAd.SqlEx.Core ,是一个很好的插件 using xLiAd.SqlEx.Core.Helper; Expression<Func<Reported ...