Abp小试牛刀之 图片上传
图片上传是很常见的功能,里面有些固定的操作也可以沉淀下来。
本文记录使用Abp vNext做图片上传的姿势。
本文的技术核心与Abp无关,Abp只是手段!
目标
- 上传图片----->预览图片----->确定保存
- 支持集群部署

实现思路:
① 上传图片要使用WebAPI特定媒体类型:multipart/form-data;
② 因为要做图片预览,故在上传时利用AbpCache做一个临时缓存,返回图片Id;
③ 前端利用FileReader渲染预览图;
④ [确定]: 发起持久化WebAPI(利用第②步返回的图片Id)
为什么强调支持集群部署?
就这个功能而言,[上传预览]和[确定保存]是两次Http WebAPI请求。
如果服务端使用的是Redis等进程外缓存: 那这正好是一个Stateless应用功能,集群环境次功能无惧!
如果服务端使用的是进程内缓存:在集群环境,前后两次请求有可能打到不同的App服务,后置的[确定保存]WebAPI因此可能报错, 此处需要做 [会话亲和性] Session affinity
实践
利用Abp做图片上传
IFormFile能力如下红框:

下面将图片二进制流转化为 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.NETCore官方文档:
- Abp默认的IDistributedCache实现是分布式内存缓存;
- 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托管服务,具备多实例自动缩放的能力,
其有关会话亲和性的配置如图:

3. K8S nginx-ingress
注解nginx.ingress.kubernetes.io/affinity在入口的所有上游中启用和设置亲和性类型。
这样,请求将总是被定向到相同的上游服务器。
https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/

That's All
本文以常见的图片上传功能为例,实战演练了Abp的缓存和持久化能力;
引申出对有状态应用配置会话亲和性,部署方式要结合业务功能。
希望对大家有所帮助!
Abp小试牛刀之 图片上传的更多相关文章
- Asp.Net Mvc 使用WebUploader 多图片上传
来博客园有一个月了,哈哈.在这里学到了很多东西.今天也来试着分享一下学到的东西.希望能和大家做朋友共同进步. 最近由于项目需要上传多张图片,对于我这只菜鸟来说,以前上传图片都是直接拖得控件啊,而且还是 ...
- 06.LoT.UI 前后台通用框架分解系列之——浮夸的图片上传
LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...
- JS图片上传预览插件制作(兼容到IE6)
其实,图片预览功能非常地常见.很意外,之前遇到上传图片的时候都不需要预览,也一直没有去实现过.现在手上的项目又需要有图片预览功能,所以就动手做了一个小插件.在此分享一下思路. 一.实现图片预览的一些方 ...
- HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术
最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...
- 对百度的UEditor多图片上传的一些补充
我已经写了一篇文章关于百度的UEditor提取多图片上传模块.如果还没有看过,请点击以下链接查看 http://www.cnblogs.com/luke1006/p/3719029.html 出差了两 ...
- 使用localResizeIMG3+WebAPI实现手机端图片上传
前言 惯例~惯例~昨天发表的使用OWIN作为WebAPI的宿主..嗯..有很多人问..是不是缺少了什么 - - 好吧,如果你要把OWIN寄宿在其他的地方...代码如下: namespace Conso ...
- TinyMCE的使用(包括汉化及本地图片上传功能)
TinyMCE我就不多介绍了,这是下载地址:https://www.tinymce.com/download/ 下载下来是英文版,要汉化也很简单.首先去网上随便下载个汉化包,然后把汉化包解压后的lan ...
- 包含修改字体,图片上传等功能的文本输入框-Bootstrap
通过jQuery Bootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色: 在Mac和window平台下自动针对常用操作绑定热键 可以拖拽插入图片,支持图片上传(也可以获取移动设 ...
- PHP多图片上传实例demo
upload.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...
随机推荐
- Java + maven + httpclient + testng + poi实现接口自动化
一.maven中引入httpclient.testng.poi依赖包 <project xmlns="http://maven.apache.org/POM/4.0.0" x ...
- jvm系列(一)运行时数据区
C++程序员肩负着每一个对象生命周期开始到终结的维护责任.Java程序员则可以借助自动内存管理机制,不需要自己手动去释放内存.由虚拟机进行内存管理,不容易出现内存泄漏和内存溢出的问题,但是一旦出现这些 ...
- Bootstrap Blazor 组件介绍 Table (一)自动生成列功能介绍
Bootstrap Blazor 是一套企业级 UI 组件库,适配移动端支持各种主流浏览器,已经在多个交付项目中使用.通过本套组件可以大大缩短开发周期,节约开发成本.目前已经开发.封装了 70 多个组 ...
- LeetCode 043 Multiply Strings
题目要求:Multiply Strings Given two numbers represented as strings, return multiplication of the numbers ...
- 在之前的EventHandler中的参数类型必须继承EventArgs,现在已经去掉这个约束了。
分别是vs2008和vs2012的对比,可以看到2012已经去掉了约束条件.
- Python+爬虫+xlwings发现CSDN个人博客热门文章
☞ ░ 前往老猿Python博文目录 ░ 一.引言 最近几天老猿博客的访问量出现了比较大的增长,从常规的1000-3000之间波动的范围一下子翻了将近一倍,粉丝增长从日均10-40人也增长了差不多一倍 ...
- PyQt学习随笔:QTableWidget的visualRow、visualColumn、logicalRow、logicalColumn(可见行、逻辑行、可见列、逻辑列)相关概念及方法探究
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概念 关于逻辑行logicalRow.列logicalColumn和可见行visualRow.列 ...
- PyQt(Python+Qt)学习随笔:窗口对象尺寸调整相关的函数resize、showMaximized、showNormal、showMinimized
resize(width,height) resize可以直接调整窗口的尺寸,调整效果类似于鼠标直接拉伸或缩小窗口,但窗口大小的最大值.最小值受窗口的sizePolicy.sizeHint.minim ...
- 深海 => 暴力扫描挖掘机
平时总是联动这个联动那个,写一些小脚本,感觉零碎又没啥意思,想把市面上一些比较知名的工具集合一下,弄个方便点的躺着挖洞的工具,看看效果会不会更好,暂时名字取深海吧,估计又是一个迟迟不填的坑,灌灌灌灌水
- 用python讲解数据结构之树的遍历
树的结构 树(tree)是一种抽象数据类型或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合 它具有以下的特点: ①每个节点有零个或多个子节点: ②没有父节点的节点称为根节点: ③ ...