图片上传是很常见的功能,里面有些固定的操作也可以沉淀下来。

本文记录使用Abp vNext做图片上传的姿势。

本文的技术核心与Abp无关,Abp只是手段!

目标

  1. 上传图片----->预览图片----->确定保存
  2. 支持集群部署

实现思路:

① 上传图片要使用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官方文档:

  1. Abp默认的IDistributedCache实现是分布式内存缓存;
  2. 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小试牛刀之 图片上传的更多相关文章

  1. Asp.Net Mvc 使用WebUploader 多图片上传

    来博客园有一个月了,哈哈.在这里学到了很多东西.今天也来试着分享一下学到的东西.希望能和大家做朋友共同进步. 最近由于项目需要上传多张图片,对于我这只菜鸟来说,以前上传图片都是直接拖得控件啊,而且还是 ...

  2. 06.LoT.UI 前后台通用框架分解系列之——浮夸的图片上传

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  3. JS图片上传预览插件制作(兼容到IE6)

    其实,图片预览功能非常地常见.很意外,之前遇到上传图片的时候都不需要预览,也一直没有去实现过.现在手上的项目又需要有图片预览功能,所以就动手做了一个小插件.在此分享一下思路. 一.实现图片预览的一些方 ...

  4. HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术

    最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...

  5. 对百度的UEditor多图片上传的一些补充

    我已经写了一篇文章关于百度的UEditor提取多图片上传模块.如果还没有看过,请点击以下链接查看 http://www.cnblogs.com/luke1006/p/3719029.html 出差了两 ...

  6. 使用localResizeIMG3+WebAPI实现手机端图片上传

    前言 惯例~惯例~昨天发表的使用OWIN作为WebAPI的宿主..嗯..有很多人问..是不是缺少了什么 - - 好吧,如果你要把OWIN寄宿在其他的地方...代码如下: namespace Conso ...

  7. TinyMCE的使用(包括汉化及本地图片上传功能)

    TinyMCE我就不多介绍了,这是下载地址:https://www.tinymce.com/download/ 下载下来是英文版,要汉化也很简单.首先去网上随便下载个汉化包,然后把汉化包解压后的lan ...

  8. 包含修改字体,图片上传等功能的文本输入框-Bootstrap

    通过jQuery Bootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色: 在Mac和window平台下自动针对常用操作绑定热键 可以拖拽插入图片,支持图片上传(也可以获取移动设 ...

  9. PHP多图片上传实例demo

    upload.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...

随机推荐

  1. java base64加解密

    接上篇java Base64算法. 根据之前过程使用base64加解密,所以写成了工具类. 代码示例; public class Base64Util { private static Logger ...

  2. 锐安信sslTrus与GeoTrust SSL证书的对比

    当您想要为您的网站购买一款SSL证书时,是不是既想要价格便宜,又想要安全性能服务好的证书,最后又在品牌上犹豫不决?如何选择SSL证书?哪款SSL证书是最适合您的?本文将详细对比分析锐成信息平台上畅销品 ...

  3. 单例模式与它的七种java实现方式

    定义 单例模式是一个比较简单的模式,其定义如下: 确保某一个类只有一个实例,而且自行实例化,并向整个系统提供这个实力. 优点: 1.由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要 ...

  4. IntelliJ IDEA 2020.3正式发布,年度最后一个版本很讲武德

    仰不愧天,俯不愧人,内不愧心.关注公众号[BAT的乌托邦],有Spring技术栈.MyBatis.JVM.中间件等小而美的原创专栏供以免费学习.分享.成长,拒绝浅尝辄止.本文已被 https://ww ...

  5. Netty 搭建 WebSocket 服务端

    一.编码器.解码器 ... ... @Autowired private HttpRequestHandler httpRequestHandler; @Autowired private TextW ...

  6. 第8.7节 Python类__new__方法和构造方法关系深入剖析:__new__方法执行结果对__init__的影响案例详解

    一. 引言 前面章节介绍了类中的构造方法和__new__方法,并分析了二者执行的先后顺序关系.__new__方法在__init__方法前执行,__new__方法执行后才返回实例对象,也就是说__new ...

  7. 关于Python链式赋值的赋值顺序问题

    在<第4.7节 Python特色的序列解包.链式赋值.链式比较>一文中,老猿这样介绍的: 链式赋值是用一行语句将多个变量赋值为同一个值,语法如下: 变量1=变量2=变量n=赋值表达式 该语 ...

  8. 转:正则表达式的先行断言(lookahead)和后行断言(lookbehind)

    正则表达式的先行断言和后行断言一共有4种形式: (?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion) (?!pattern) 零宽 ...

  9. .NET 面试题汇总(带答案)

    1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么? 答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方式可以保证无论何 ...

  10. 【题解】The Last Hole! [CF274C]

    [题解]The Last Hole! [CF274C] 传送门:\(\text{The Last Hole!}\) \(\text{[CF274C]}\) [题目描述] 给出平面上 \(n\) 个圆的 ...