阿里云平台OSS对象存储
OSS即“OpenStorageService”,概念上没啥新意,就是本地存储搬到阿里云平台上了,单个存储对象大小可以达到5G,看了下阿里的OSS教程java版本,
使用原生js和servlet实现,这基本就能看不能用,为了做点通用的,我们来玩一把OSS,抓下时髦的尾巴。
准备:
Idea2019.03/Gradle6.0.1/JDK11.0.4/Lombok0.28/SpringBoot2.2.4RELEASE/mybatisPlus3.3.0/Soul2.1.2/Dubbo2.7.5/Mysql8.0.11/Vue2.5/OSS
难度: 新手--战士--老兵--大师
目标:
1.Vue前端+Java后端结合实现OSS图片对象存储
步骤:
为了遇见各种问题,同时保持时效性,我尽量使用最新的软件版本。代码地址:https://github.com/xiexiaobiao/vehicle-shop-admin
1 OSS简介
- 略
阿里云官网资料太多,请君移步,我就不搬运了。
2 分析原理
很多时候,我们上传文件都是前端把待传数据先给后端应用服务器,然后由后端Server再分类存储到比如Mysql,Mongo等等,由于现代的前端功能已十分强大,
当然可以直接由前端上传文件直接到OSS,后端Server只需要告诉上传到哪里以及如何上传即可,这样可以降低后端负载, 流程如下:
- 用户每次需要上传时,web端先向应用服务器请求上传Policy(就是OSS存储地址和目录、账号密码信息、签名、过期信息等)和 回调(上传过程和结果信息反馈给需要的服务器,做展示/记录等用,户上传完文件后,不会直接得到返回结果,而是先通知应用服务器,再把结果转达给用户)。
- 应用服务器返回给web端上传Policy和回调设置。
- web端直接向OSS发送文件上传请求,并上传文件。
- OSS根据用户的回调设置,发送回调请求给应用服务器。
- 应用服务器返回响应给OSS。
- OSS将应用服务器返回的内容返回给web端。
这里有个模式问题,其实如果把OSS相关的Policy信息直接写在前端代码里,然后直接上传文件,也可以的,只是安全性会让人心慌,算是方案一,
如果仍然由后端提供Policy而不要回调信息,直接返回信息给web端就是方案二,上面的方式就是方案三了,我这里以方案三说事。
3 看前端代码
使用elementUI的upload组件,具体可以见elementUI的官方组件介绍,了解各属性含义:src/components/Upload/singleUpload.vue:
<el-upload
ref="upload"
:action="useOss?ossUploadUrl:minioUploadUrl"
:limit="1"
:data="useOss?dataObj:null"
list-type="picture"
:multiple="false"
:file-list="fileList"
:auto-upload= "autoUpload"
:show-file-list="true"
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-success="handleUploadSuccess"
:on-preview="handlePreview">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<!--以下为如果手动触发上传的按钮-->
<!-- <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>-->
<div slot="tip" class="el-upload__tip">只能上传一张jpg/png文件,且不超过10MB</div>
</el-upload>
上面代码的核心要点:
- 并通过:auto-upload设置为自动提交,即只要选择好文件后就自动提交,当然也可以先选好文件,再通过按钮触发提交,见我注释掉的部分。
- :before-upload="beforeUpload" 即真实开始上传文件前做的工作:
beforeUpload(file) {
let _self = this;
if(!this.useOss){
//不使用oss不需要获取策略
returntrue;
}
returnnewPromise((resolve, reject) => {
policy().then(response => {
// 返回的对象,多一层data封装,故写为response.data.data
_self.dataObj.policy = response.data.data.policy;
_self.dataObj.signature = response.data.data.signature;
_self.dataObj.ossaccessKeyId = response.data.data.accessKeyId;
_self.dataObj.key = response.data.data.dir + '/'+this.fileNameUUID +'${filename}';
_self.dataObj.dir = response.data.data.dir;
_self.dataObj.host = response.data.data.host;
// _self.dataObj.callback = response.data.data.callback;
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
},
以上通过axios向后端发异步请求,policy()方法我放在其他文件中了,就是通过axios的GET访问去后端获取Policy,然后再赋值到当前的存储变量上,
这样就取得了Policy信息,注意_self.dataObj.key这里的 '/' 不能放 '${filename}' 前,否则oss存储时会自动增加一层目录目录!!只要以上正确,基本就能自动完成上传了。
4 看后端代码
OSS专用的依赖:
compile group: 'com.aliyun.oss', name: 'aliyun-sdk-oss', version: '3.8.1'
compile group: 'com.aliyun', name: 'aliyun-java-sdk-core', version: '4.5.0'
compile group: 'com.aliyun', name: 'aliyun-java-sdk-sts', version: '3.0.1'
com.biao.shop.stock.impl.AliyunOssServiceImpl
, 即上面的前端请求Policy的处理对象,Controller我就不展示了,就是响应前端REST,然后调用这个服务:
@Service
publicclass AliyunOssServiceImpl implements AliyunOssService { privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(AliyunOssServiceImpl.class);
@Value("${aliyun.oss.policy.expire}")
privateint ALIYUN_OSS_EXPIRE;
@Value("${aliyun.oss.maxSize}")
privateint ALIYUN_OSS_MAX_SIZE;
@Value("${aliyun.oss.callback}")
private String ALIYUN_OSS_CALLBACK;
@Value("${aliyun.oss.bucketName}")
private String ALIYUN_OSS_BUCKET_NAME;
@Value("${aliyun.oss.endpoint}")
private String ALIYUN_OSS_ENDPOINT;
@Value("${aliyun.oss.dir.prefix}")
private String ALIYUN_OSS_DIR_PREFIX; private OSSClient ossClient; @Autowired
public AliyunOssServiceImpl(OSSClient ossClient) {
this.ossClient = ossClient;
} @Override
public ObjectResponse<AliyunPolicy> policy() { ObjectResponse<AliyunPolicy> result = new ObjectResponse<>();
// 存储目录,按天区分
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String dir = ALIYUN_OSS_DIR_PREFIX + LocalDateTime.now().toLocalDate().format(dtf);
// 签名有效期
long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
Date expiration = new Date(expireEndTime);
// 文件大小
long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
// 回调
AliyunCallbackParam callback = new AliyunCallbackParam();
callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
callback.setCallbackBodyType("application/x-www-form-urlencoded");
// 提交节点
String action = "http://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
try {
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
String policy = BinaryUtil.toBase64String(binaryData);
String signature = ossClient.calculatePostSignature(postPolicy);
// 对"callback"属性进行base64编码编码
String callbackData = BinaryUtil.toBase64String(
JacksonUtil.convertToJson(callback).getBytes(StandardCharsets.UTF_8));
// 返回结果
AliyunPolicy aliyunPolicy = new AliyunPolicy();
aliyunPolicy.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
aliyunPolicy.setPolicy(policy);
aliyunPolicy.setSignature(signature);
aliyunPolicy.setExpire(String.valueOf(expireEndTime));
aliyunPolicy.setDir(dir);
aliyunPolicy.setCallback(callbackData);
aliyunPolicy.setHost(action);
result.setCode(RespStatusEnum.SUCCESS.getCode());
result.setMessage(RespStatusEnum.SUCCESS.getMessage());
result.setData(aliyunPolicy);
} catch (Exception e) {
LOGGER.error("signature failed !!", e);
}
return result;
}
}
以上我做了个响应的对象封装,ObjectResponse{code,message,data}
,关于OSS的账号密码信息,我都放在配置文件统一管理;
注意OSSClient要通过Configuration类中生成一下。可以看到以上设置了一系列的OSS存储政策(Policy):存储目录,按天区分;签名有效期;文件大小限制;
回调地址;提交上传的OSS地址等等。
5 再看前端代码:
src/components/Upload/singleUpload.vue:
这是处理每次上传文件完成之后的逻辑,如果设置为可以上传多个文件,那么这个会执行多次。因为OSS存储,如果同目录下文件同名就直接覆盖,
它不会询问大家意见的!所以这里有个小技巧:我通过getFileNameUUID自动生成个随机前缀,绑定到一个本地变量,每次上传成功,都刷新一下,
再混入url和key值,perfect!!
handleUploadSuccess(res, file) {
this.showFileList = true;
this.fileList.pop();
let url = this.dataObj.host + '/' + this.dataObj.dir + '/' + this.fileNameUUID+ file.name;
if(!this.useOss){
//不使用oss直接获取图片路径
url = res.data.url;
}
this.fileList.push({name: this.fileNameUUID + file.name, url: url});
// 每次上传完成,更新fileNameUUID
this.getFileNameUUID();
this.emitInput(this.fileList[0].url);
},
/*随机生成文件前缀,防止同名覆盖*/
getFileNameUUID(){
this.fileNameUUID = (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(0,4);
},
效果展示,上传中,可以看到进度:
完成后,可以直接删除,或者查看大图,如果做的完美一点,点删除,要触发OSS删除事件,我代码省略没写啦。
当然,还有些其他组件,如其他一些封装类Bean,我就不细说啦,直接看我代码即可!
@Data
publicclass AliyunPolicy {
private String AccessKeyId;
private String host;
private String policy;
private String signature;
private String expire;
private String callback;
private String dir;
}
后记:
1,我买了一套阿里的云产品:ECS 弹性计算服务器,RDS云关系DB,OSS对象存储,把我自己开发的一套前后端都部署上了,
体验就是真羡慕有钱人,起步价的机器比如2G内存,上5个微服务基本就跑满了!在想尽了各种省内存办法又没辙的情形下,我
只能又拉了一台ECS,才架起了网关,注册中心,内存消耗记录:Nacos 0.4G,zookeeper 0.1G,微服务模块5个:authority 200M,
customer 200M,stock 200M,order 200M,business 200M,其他Nginx 100M,souladmin 0.2G,soulbootstrap 0.2G,另外就是
传说Jetty比Tomcat省内存,反正我没看出来,估计是服务数量级不够。
2,如果公司money多,还是推荐上这些云服务的,至少不会上演最近的微盟删库但跑路不成功的事件,云服务自动有各种容灾备份
机制,如异地备,定期备,不亦乐乎?
3,关于callback没细说,具体看代码吧,代码是最最好的老师。
全文完!
推荐阅读:
- 1 Dubbo学习系列之十七(微服务Soul网关)
- 2 Docker部署RocketMQ
- 3 流式计算(五)-Flink 计算模型
- 4 流式计算(四)-Flink Stream API 篇二
- 5 流式计算(三)-Flink Stream 篇一
阿里云平台OSS对象存储的更多相关文章
- 阿里云之OSS 开放存储服务开发笔记
在使用云服务以后,你不用考虑他是否能承受压力,而是费用.不要考虑是否被攻击,而是他的API实现.本人开发阿里云服务也走了些崎岖之路,写下以备忘之. 阿里云的开放存储服务可以提供文件的存储服务,开放了上 ...
- 22.Java面试学习平台-整合OSS对象存储
SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...
- PHP 上传文件至阿里云OSS对象存储
简述 1.阿里云开通对象存储服务 OSS 并创建Bucket 2.下载PHP SDK至框架扩展目录,点我下载 3.码上code 阿里云操作 开通对象存储服务 OSS 创建 Bucket 配置Acces ...
- iOS使用阿里云OSS对象存储 (SDK 2.1.1)
最近项目中用到了阿里云OSS对象存储,用来存储APP中图片.音频等一些数据.但坑爹的阿里云居然在11月20日将SDK版本更新到了2.1.1,然而网上给出的教程都是1.*版本的(针对iOS),两个版本所 ...
- Java使用阿里云OSS对象存储上传图片
原 Java使用阿里云OSS对象存储上传图片 2017年03月27日 10:47:28 陌上桑花开花 阅读数 26804更多 分类专栏: 工作案例总结 版权声明:本文为博主原创文章,遵循CC 4.0 ...
- SpringBoot整合阿里云OSS对象存储实现文件上传
1. 准备工作: 一.首先登录阿里云OSS对象存储控制台创建一个Bucket作为你的存储空间. 二.创建Access Keyan按要求创建进行,这里的方法步骤我就不展现出来了,你们可以自行查询阿里云文 ...
- 架构师小跟班:教你从零开始申请和配置七牛云免费OSS对象存储(不能再详细了)
背景 之前为了练习Linux系统使用,在阿里云上低价买了一台服务器(网站首页有活动链接,传送门),心里想反正闲着也是闲着,就放了一个网站上去.现在随着数据越来越多,服务器空间越来越吃紧,我就考虑使用七 ...
- 云计算:创业的好时机——上海够快网络科技有限公司总经理蒋烁淼专访(评价阿里云的OSS的4个优点)(够快科技正式宣布已成功挂牌新三板)
云存储是云计算目前的热点之一,Dropbox.Box等产品的风靡,公司因此获得极高估值,都印证了这一点.但云存储对技术和资金要求都比较高,竞争也非常激烈,挑战巨大.国外云存储公司有亚马逊的云平台作为支 ...
- 阿里云基于OSS的云上统一数据保护方案2.0技术解析
近年来,随着越来越多的企业从传统经济向数字经济转型,云已经渐渐成为数据经济IT新常态.核心业务系统上云,云上的业务创新,这些都产生了大量的业务数据,这些数据也成为了企业最重要的资产.资源. 阿里云基于 ...
- 阿里云基于OSS的云上统一数据保护方案2.0正式发布
近年来,随着越来越多的企业从传统经济向数字经济转型,云已经渐渐成为数据经济IT新常态.核心业务系统上云,云上的业务创新,这些都产生了大量的业务数据,这些数据也成为了企业最重要的资产.资源.阿里云基于O ...
随机推荐
- bug的合规描述
bug的合格描述: 发现问题的版本bug的合格描述: 开发人员需要知道出现问题的版本,才能够获取对应版本的代码来重现故障问题出现的环境 环境分为硬件环境和软件环境,详细的环境描述有利于故障的重现( ...
- Ubuntu13 安装vim
问题 由于系统没有vim,只有vi,而vi 编辑文件时比较麻烦,不易操作,还没有关键词高亮显示等,故想安装vim 输入命令: sudo apt install vim 报错,找不到 apt 命令,即没 ...
- unicode编码 asis_2019_unicorn_shop
这题就是让我们购买第四个商品 当我们输入price为1337.0的时候他会报错,显示要我们只输入一个字符 那么我们就要想怎样用一个字符来表示一个比1337还要大的数字 答案是unicode 编码 (题 ...
- vim系列-文本操作篇
基数行与偶数行分组 使用Vim的替换命令,可以轻松地将基数行和偶数行分组: %s/\(^.*$\)\n\(^.*$\)/\1 \2/g 然后,删除所有的基数行: %s/^.*$\n\(^.*$\)/\ ...
- 用SignalR和Layui搭建自己的web聊天网站
1.开发背景 之前是做项目一直有一个困扰,就是如何进行及时通讯,本人.Net开发,不太想用别人的接口,然后偶然的机会知道了SignalR,那么什么是SignalR呢? 2.SignalR简介 ASP. ...
- 玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之保障热门产品发售服务安全稳定
本文分享自天翼云开发者社区<玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之保障热门产品发售服务安全稳定>,作者:天翼云社区官方账号 随着社会经济的发展和人民生活水平的提高,越 ...
- SQL注入之布尔盲注
SQL注入之布尔盲注 一.布尔盲注原理 布尔盲注是一种基于布尔逻辑的SQL注入攻击技术,其核心原理是通过构造特定的SQL查询语句,利用应用程序对查询结果的不同响应(通常是真或假)来逐步推断数据库中的信 ...
- 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-13- iframe操作-中篇(详细教程)
1.简介 按照计划今天就要用实际的例子进行iframe自动化测试.宏哥还是用之前找到的一个含有iframe的网页(QQ邮箱和163邮箱),别的邮箱宏哥就没有细看了,可能后期这两个邮箱页面优化升级,也就 ...
- pycharm上传github问题:rejected
我从pycharm上传项目时,遇到的问题: 以下是一些解决思路: 这个错误提示表明,你在尝试将本地代码推送到远程仓库时,远程仓库中已经包含了你本地尚未获取的更改.换句话说,远程仓库的代码比你的本地代码 ...
- stay:将代码翻译为Gif动图,妈妈再也不用担心我调试找不到bug了
本文首发于微信公众号:呼哧好大枫.原作者与本文作者是同一人. 平常在做算法题或者是 debug 的时候很需要一款能够实时地将代码执行逻辑和数据以图形化的形式渲染出来的工具.之前尝试了几款(visual ...