Abp小试牛刀之 图片上传

简介: 图片上传是很常见的功能,里面有些固定的操作也可以沉淀下来。本文记录使用Abp vNext做图片上传的姿势。

目标


  1. 上传图片----->预览图片----->确定保存


  1. 支持集群部署


5eedebfa56551c257b5fe5d440d17bd6.png


实现思路:


1. 上传图片要使用WebAPI特定媒体类型:multipart/form-data;


2. 因为要做图片预览,故在上传时利用AbpCache做一个临时缓存,返回图片Id


3. 前端利用FileReader渲染预览图;


4.  [确定]: 发起持久化WebAPI(利用第2步返回的图片Id)


为什么强调支持集群部署?


就这个功能而言,[上传预览]和[确定保存]是两次Http WebAPI请求。


如果服务端使用的是Redis等进程外缓存: 那这正好是一个Stateless应用功能,集群环境无惧!


如果服务端使用的是进程内缓存:在集群环境,前后两次请求有可能打到不同的App服务,后置的[确定保存]WebAPI因此可能报错, 此处需要做 [会话亲和性] Session affinity


实践


利用Abp做图片上传


IFormFile能力如下红框:


a3bd999ae35f5224366479dd08ece22c.png


下面将图片二进制流转化为 base64字符串,注入Abp缓存组件IDistributedCache<string>;缓存图片字符串1小时。


[上传预览], [确定保存]的API完整代码如下:


/// <summary>
       /// 上传预览, 返回待上传的图片id,Content-Type:multipart/form-data
       /// </summary>
       /// <returns></returns>
       [Consumes("multipart/form-data")]
       [Route("upload/preview")]
       [ProducesResponseType(typeof(Guid),200)]
       [HttpPost]
       public async Task<Guid> UploadPicPreviewAsync(IFormFile uploadedFile)
       {
           var formFileName = uploadedFile.FileName;
           if (!new[] { ".png", ".jpg", ".bmp" }.Any((item) => formFileName.EndsWith(item)))
           {
               throw new AbpValidationException("您上传的文件格式必须为png、jpg、bmp中的一种");
           }
           byte[] bytes;
           using (var bodyStream = uploadedFile.OpenReadStream())
           {
               using (var m = new MemoryStream())
               {
                   await bodyStream.CopyToAsync(m);
                   bytes = m.ToArray();
               }
           }
           string base64 = Convert.ToBase64String(bytes);
           var bgId = Guid.NewGuid();
           _cache.Set($"{CurrentUser.TenantId}:bg:{bgId}", base64, new DistributedCacheEntryOptions { SlidingExpiration = new TimeSpan(1, 0, 0) });
           return bgId;
       }
       /// <summary>
       /// 保存图片,要使用到前置API的预览图片id
       /// </summary>
       /// <param name="createPictureInput"></param>
       /// <returns></returns>
       [Route("upload/")]
       [HttpPost]
       public async Task<bool> UploadPicAsync([FromBody] CreatePictureInput createPictureInput)
       {
           var based64 = await _cache.GetAsync($"{CurrentUser.TenantId}:bg:{createPictureInput.PreviewPicId}");
           if (string.IsNullOrEmpty(based64))
               throw  new AbpException("Cache Hotmap Picture do not find");
           var model = ObjectMapper.Map<CreatePictureInput, Picture>(createPictureInput);
           model.ProfileId = CurrentUser.TenantId;
           model.BlobStorage = Convert.FromBase64String(based64);
           return await _pictures.InsertAsync(model)!= null;
       }


Default implementation of the IDistributedCache interface is the MemoryDistributedCache which works in-memory.

The Distributed Memory Cache (AddDistributedMemoryCache) is a framework-provided implementation of IDistributedCache that stores items in memory. The Distributed Memory Cache isn't an actual distributed cache. Cached items are stored by the app instance on the server where the app is running.


以上两段文字来自 Abp和ASP.NET Core官方文档:


  1. Abp默认的IDistributedCache实现是分布式内存缓存;


  1. ASP.NETCore 分布式内存缓存是框架内置的,是一个假的分布式缓存,实际是单纯的内存缓存。


在没有使用真实分布式缓存的情况下, 需要对前后两个API配置会话亲和性。


会话亲和性


下面从nginx、Azure、k8s ingress 三角度配置[会话亲和性],(全站生效)  


会话亲和性的实现原理,是在接受客户端首次请求时响应某个cookie,服务器会认定使用同一个cookie的请求为一个会话。


1. nginx


属于nginx负载均衡的范畴:https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/


示例如下:


upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

2. Azure App Service


Azure pp Service是Azure云平台提供的App托管服务,具备多实例自动缩放的能力, 其有关会话亲和性的配置如图:


548b7085aeed4217cd2cbeba7bfc1efa.png


3. K8S nginx-ingress


注解nginx.ingress.kubernetes.io/affinity在入口的所有上游中启用和设置亲和性类型。


这样,请求将总是被定向到相同的上游服务器。


https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/


bfdae82108d91289667a440b4fa555a9.png


That's All


本文以常见的图片上传功能为例,实战演练了Abp的缓存和持久化能力;引申出对有状态应用(集群)配置会话亲和性。


部署配置要结合业务功能,希望对大家有所帮助!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
7月前
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
282 0
|
7月前
|
JavaScript Java 测试技术
儿童预防接种预约微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
儿童预防接种预约微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
54 1
|
7月前
|
JavaScript Java 测试技术
畅阅读微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
畅阅读微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
43 0
|
7月前
|
JavaScript Java 测试技术
用于日语词汇学习的微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
用于日语词汇学习的微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
73 0
|
7月前
|
JavaScript Java 测试技术
基于小程序的小说阅读器+springboot+vue.js附带文章和源代码设计说明文档ppt
基于小程序的小说阅读器+springboot+vue.js附带文章和源代码设计说明文档ppt
74 0
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的壁纸网站附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的壁纸网站附带文章和源代码设计说明文档ppt
49 1
|
7月前
|
JavaScript Java 测试技术
基于微信小程序的课堂点名系统springboot+vue.js附带文章和源代码设计说明文档ppt
基于微信小程序的课堂点名系统springboot+vue.js附带文章和源代码设计说明文档ppt
70 3
|
7月前
|
JavaScript Java 测试技术
阳光电脑公司的维修服务微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
阳光电脑公司的维修服务微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
40 1
|
7月前
|
JavaScript Java 测试技术
懂球短视频微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
懂球短视频微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
42 2
|
7月前
|
JavaScript Java 测试技术
高质量阅读微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
高质量阅读微信小程序+springboot+vue.js附带文章和源代码设计说明文档ppt
35 1

相关实验场景

更多