概述
Spring Boot整合Minio后,前端的文件上传有两种方式:
-
文件上传到后端,由后端保存到Minio
这种方式好处是完全由后端集中管理,可以很好的做到、身份验证、权限控制、文件与处理等,并且可以做一些额外的业务逻辑,比如生成缩略图、提取元数据等。
缺点也很明显:
所以,实际上我们不会把文件传到后端,而是直接传给Minio,其实这也符合OSS服务的使用方式。
-
延迟时间高了,本来花费上传一次文件的时间,现在多了后端保存到Minio的时间
-
后端资源占用,后端本来可以只处理业务请求,现在还要负责文件流,增加了性能压力
-
单点故障,Minio即便做了集群,但是如果后端服务器故障,也会导致Minio不可用
-
-
文件向后端申请上传凭证,然后直接上传到Minio
为了避免Minio被攻击,我们需要结合后端,让后端生成并返回一个有时效的上传凭证,前端拿着这个凭证才能去上传,通过这种方式,我们可以做到一定程度的权限控制,本文要分享的就是这种方式。
环境准备
部署好的Minio环境:http://mylocalhost:9001
Spring Boot整合Minio
先引入Minio依赖
pom.xml
<dependency>
????<groupId>io.minio</groupId>
????<artifactId>minio</artifactId>
????<version>7.1.0</version>
</dependency>
然后定义配置信息
application.yml
minio:
??endpoint:?http://mylocalhost:9001
??accessKey:?minio
??secretKey:?minio123
??bucket:?demo
定义一个属性类
@Component
@ConfigurationProperties(prefix?=?"minio")
public?class?MinioProperties?{
????/**
?????*?对象存储服务的URL
?????*/
????private?String?endpoint;
????/**
?????*?Access?key就像用户ID,可以唯一标识你的账户
?????*/
????private?String?accessKey;
????/**
?????*?Secret?key是你账户的密码
?????*/
????private?String?secretKey;
????/**
?????*?默认文件桶
?????*/
????private?String?bucket;
????
????...
}
定义Minio配置类
@Configuration
public?class?MinioConfig?{
????@Bean
????public?MinioClient?minioClient(MinioProperties?properties){
????????try?{
????????????MinioClient.Builder?builder?=?MinioClient.builder();
????????????builder.endpoint(properties.getEndpoint());
????????????if?(StringUtils.hasLength(properties.getAccessKey())?&&?StringUtils.hasLength(properties.getSecretKey()))?{
????????????????builder.credentials(properties.getAccessKey(),properties.getSecretKey());
????????????}
????????????return?builder.build();
????????}?catch?(Exception?e)?{
????????????return?null;
????????}
????}
}
现在启动服务即可。
上传凭证
写一个接口,返回上传凭证
@RequestMapping(value?=?"/presign",?method?=?{RequestMethod.POST})
public?Map<String,?String>?presign(@RequestBody?PresignParam?presignParam)?{
????//?如果前端不指定桶,那么给一个默认的
????if?(StringUtils.isEmpty(presignParam.getBucket()))?{
????????presignParam.setBucket("demo");
????}
????//?前端不指定文件名称,就给一个UUID
????if?(StringUtils.isEmpty(presignParam.getFilename()))?{
????????presignParam.setFilename(UUID.randomUUID().toString());
????}
????//?如果想要以子目录的方式保存,就在前面加上斜杠来表示
????//????????presignParam.setFilename("/2023/"?+?presignParam.getFilename());
????//?设置凭证过期时间
????ZonedDateTime?expirationDate?=?ZonedDateTime.now().plusMinutes(10);
????//?创建一个凭证
????PostPolicy?policy?=?new?PostPolicy(presignParam.getBucket(),?presignParam.getFilename(),?expirationDate);
????//?限制文件大小,单位是字节byte,也就是说可以设置如:只允许10M以内的文件上传
????//????????policy.setContentRange(1,?10?*?1024);
????//?限制上传文件请求的ContentType
????//????????policy.setContentType("image/png");
????try?{
????????//?生成凭证并返回
????????final?Map<String,?String>?map?=?minioClient.presignedPostPolicy(policy);
????????for?(Map.Entry<String,?String>?entry?:?map.entrySet())?{
????????????System.out.println(entry.getKey()?+?"?=?"?+?entry.getValue());
????????}
????????return?map;
????}?catch?(MinioException?|?InvalidKeyException?|?IOException?|?NoSuchAlgorithmException?e)?{
????????e.printStackTrace();
????}
????return?null;
}
上面的示例代码可以知道,我们还可以加一些权限认证,以判断用户是否有以下权限:
-
上传权限
-
可上传的文件大小
-
可上传的文件类型
请求参数类:
public?class?PresignParam?{
????//?桶名
????private?String?bucket;
????//?文件名
????private?String?filename;
????
????...
}
这个接口的返回结果是:
bucket:?demo
x-amz-date:?20230831T042351Z

最低0.47元/天 解锁文章
5636

被折叠的 条评论
为什么被折叠?



