人之所以痛苦,那是因为你在成长。--------magic_guo
上一篇写了fastDFS,这一片就来就写一下阿里云的OSS文件存储;相比于fastDFS,OSS的好处不用多说,只需配置即可,无需担心搭建与后期维护问题;
怎么注册OSS和开通OSS服务一起怎么获取AK与ASK这里不在进行叙述,可以根据官网的指引或者网上的教程来搞,一搜一大堆;
在分布式系统中,一般上传图片和文件的流程是:
前端带着文件----->调用文件上传服务的接口将文件转化成流的形式----->调用存储系统的接口;
上述流程正如我们上一篇所讲fastDFS的存储流程;OSS同样也有上述的上传方式,但是也有一种,图片不用经过后台的上传服务,只从服务端获取一个签名,然后前端拿着这个签名和图片直接上传给OSS存储,即OSS的“服务端签名后直传”;
这样的上传方式减轻了服务端的压力,保持了微服务的性能
流程图:
普通上传:
需要依赖:
根据oss的官方文档提供的依赖在项目中编译版本是冲突的:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>
在网上所搜了收发现很多人出现这个问题,说是版本问题,但是此解决方法有的说也有冲突,但是我的没啥问题:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>aliyun-spring-boot-dependencies</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
application.yml配置:
spring:
application:
name: shop-oss
server:
port: 8888
alibaba:
cloud:
access-key: xxxxxxxxxxxxx
secret-key: xxxxxxxxxxxxx
oss:
endpoint: xxxxxxxxxxxxx
bucket: xxxxxxxxxxxxx
controller层:
服务端接收一个MultipartFile类型的文件,然后将此文以流的形式发送至OSS存储:
@RestController
@RequestMapping("/oss")
public class OssController {
@Value("${alibaba.cloud.access-key}")
private String accessKeyId;
@Value("${alibaba.cloud.secret-key}")
private String accessKeySecret;
@Value("${alibaba.cloud.oss.endpoint}")
private String endpoint;
@Value("${alibaba.cloud.bucket}")
private String bucketName;
@Autowired
private OSS ossClient;
@RequestMapping("/getOssPath")
public String getOssPath(MultipartFile file) {
try {
//获取上传的文件输入流
InputStream inputStream = file.getInputStream();
//获取文件名称
String filename = file.getOriginalFilename();
//1.在文件名称里面添加唯一的值
String uuid = UUID.randomUUID().toString().replace("-", "");
//阿里云oss的文件名称
filename = uuid + filename;
//2 把文件按照日期进行分类
//获取当前日期
// 2021/07/31
String datePath = new DateTime().toString("yyyy/MM/dd");
//拼接
filename = datePath + "/" + filename;
ossClient.putObject(bucketName, filename, inputStream);
String url = "https://" + bucketName + "." + endpoint + "/" + filename;
return url;
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭OSSClient。
ossClient.shutdown();
}
return null;
}
}
测试结果:
OSS页面:
签名上传:
controller层:
@RestController
@RequestMapping("/oss")
public class OssController {
@Value("${alibaba.cloud.access-key}")
private String accessKeyId;
@Value("${alibaba.cloud.secret-key}")
private String accessKeySecret;
@Value("${alibaba.cloud.oss.endpoint}")
private String endpoint;
@Value("${alibaba.cloud.bucket}")
private String bucketName;
@Autowired
private OSS ossClient;
@RequestMapping("/getPolicy")
public Map<String, String> getPolicy() {
String host = "https://" + bucketName + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
String callbackUrl = "http://88.88.88.88:8888";
String dir = "user-dir-prefix/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
// PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessKeyId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return respMap;
}
}
访问此接口可以得到一个签名,然后前端拿着这个签名和图片,通过oss的验证就可以将图片存储;
前端访问的接口:http://shao-bucket.oss-cn-hangzhou.aliyuncs.com
由于我没有前端的技术,获取到签名后,使用postman不知道怎么测试此接口,等以后知道怎么调用再来修改此流程;
获取签名测试:
本文章教学视频来自:https://www.bilibili.com/video/BV1tb4y1Q74E?p=3&t=125
静下心,慢慢来,会很快!