前言:为什么需要云存储?
在分布式微服务的情况下,网关在某次负载均衡到某一个服务,且如果将文件就存储在此服务的服务器,
下次需要查看文件的时候如果负载均衡不到同一个服务,就会出问题,所以不如将文件放在同一个地方存储
阿里云文件上传方式
1、普通上传:使用java代码上传,劣势是要经过自身的服务器,但安全
2、浏览器上传,云储存账号写在js里,不安全
3、服务端签名后直传:上传的账号信息存储在应用服务器 ,上传先找应用服务器要一个防伪签名,
带签名和文件上传到服务器,就不用经过自己的服务器
服务只处理签名,不处理问价,保证加密,减轻服务压力
实现example
1、导包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependencyManagement>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这里的依赖可能有问题,个人情况是:
Cannot resolve com.aliyun.oss:aliyun-sdk-oss:3.1.0等
最后打开本地的依赖文件夹,发现实依赖的jar包没下载下来,去maven仓库下下载jar拖进去好了
不过idea上maven依赖还是会有波浪线,但不影响运行
另一种情况是,阿里云的依赖改了:
新版:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>1.0.0</version>
<dependency>
2、写配置
如果是将签名写在代码中,阿里云有教程:
https://help.aliyun.com/zh/oss/developer-reference/preface-1
但如果项目中用到了注册中心,那可以将签名写在配置文件,或者在nacos注册中心新建配置
application.yaml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key:
secret-key:
oss:
endpoint: oss-cn-guangzhou.aliyuncs.com
bucket:
application:
name:
server:
port: 30000
bootstrap.properties
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=dbb03c13-1154-47f7-be4d-ea3ac0016b95
//nacos配置中心列表配置
spring.cloud.nacos.config.extension-configs[0].data-id=oss.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
//配置中心修改后,主动刷新配置
spring.cloud.nacos.config.extension-configs[0].refresh=true
两个配置文件其实写一个就可以,可以将配置都写在boorstrap上
启动类上加入服务发现注解@EnableDiscoveryClient
3、服务端签名后直传
阿里云官方教学
https://help.aliyun.com/zh/oss/use-cases/java-1?spm=a2c4g.11186623.0.0.77b62ecc9vfeSO
要记得配置跨域访问
创建方法返回签名:
@RestController
public class OssController {
// 注入ossClient实例。
@Autowired
OSSClient ossClient;
@Value("${spring.cloud.alicloud.oss.bucket")
public String bucket;
@Value("${spring.cloud.alicloud.oss.endpoint")
private String endpoint;
@Value("${spring.cloud.alicloud.access-key")
private String accessId;
@RequestMapping("/oss/policy")
public Map<String, String> policy() {
// 填写Host地址,格式为https://bucketname.endpoint。
String host = "https://" + bucket + endpoint;
// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
String callbackUrl = "https://192.168.0.0:8888";
// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
//按服务器时间生成格式化时间作为目录名
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/";
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
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", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
}
return respMap;
}
}
运行结果: