SpringBoot + minio实现分片上传、秒传、续传
什么是minio
MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议,项目地址是https://github.com/minio/minio。
引用官网:
MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容。使用MinIO构建用于机器学习,分析和应用程序数据工作负载的高性能基础架构。
官网地址:
https://min.io/
文档地址:
https://docs.min.io/
一. 使用docker 搭建minio 服务
GNU / Linux和macOS
docker run -p 9000:9000 \
--name minio1 \
-v /mnt/data:/data \
-e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \
-e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
minio/minio server /data
windows
docker run -p 9000:9000 \
--name minio1 \
-v D:\data:/data \
-e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \
-e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
minio/minio server /data
MINIO_ROOT_USER
:为用户keyMINIO_ROOT_PASSWORD
:为用户密钥
以上搭建的都是单机版的。想要了解分布式 的方式请查看官网文档。
这就是在win的docker上运行的。
更多开源项目:https://www.yoodb.com/projects/springboot-user-manger.html
当启动后在浏览器访问http://localhost:9000
就可以访问minio的图形化界面了,如图所示:
二. 下面开始搭建springboot 环境
初始化一个springboot项目大家都会,这里不多做介绍。
主要是介绍需要引入的依赖:
org.springframework.boot
spring-boot-starter-thymeleaf
io.minio
minio
8.2.1
org.projectlombok
lombok
true
依赖可以官方文档里找:https://docs.min.io/docs/java-client-quickstart-guide.html
下面介绍配置文件:
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
#minio配置
minio:
access-key: AKIAIOSFODNN7EXAMPLE #key就是docker初始化是设置的,密钥相同
secret-key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
url: http://localhost:9000
bucket-name: wdhcr
thymeleaf:
cache: false
创建minio的配置类:
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
@Data
public class MinioConfiguration {
private String accessKey;
private String secretKey;
private String url;
private String bucketName;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.build();
}
}
使用配置属性绑定进行参数绑定,并初始化一个minio client对象放入容器中。
下面就是我封装的minio client 操作minio的简单方法的组件。
@Component
public class MinioComp {
@Autowired
private MinioClient minioClient;
@Autowired
private MinioConfiguration configuration;
/**
* @description: 获取上传临时签名,公众 号Java精选
* @dateTime: 2021/5/13 14:12
*/
public Map getPolicy(String fileName, ZonedDateTime time) {
PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);
postPolicy.addEqualsCondition("key", fileName);
try {
Map map = minioClient.getPresignedPostFormData(postPolicy);
HashMap map1 = new HashMap<>();
map.forEach((k,v)->{
map1.put(k.replaceAll("-",""),v);
});
map1.put("host",configuration.getUrl()+"/"+configuration.getBucketName());
return map1;
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
return null;
}
/**
* @description: 获取上传文件的url,公众 号Java精选,有惊喜!
* @dateTime: 2021/5/13 14:15
*/
public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(method)
.bucket(configuration.getBucketName())
.object(objectName)
.expiry(time, timeUnit).build());
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
}
return null;
}
/**
* @description: 上传文件
* @dateTime: 2021/5/13 14:17
*/
public void upload(MultipartFile file, String fileName) {
// 使用putObject上传一个文件到存储桶中。
try {
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(configuration.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
}
/**
* @description: 根据filename获取文件访问地址
* @dateTime: 2021/5/17 11:28
*/
public String getUrl(String objectName, int time, TimeUnit timeUnit) {
String url = null;
try {
url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(configuration.getBucketName())
.object(objectName)
.expiry(time, timeUnit).build());
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
}
return url;
}
}
简单说明:
使用MultipartFile接收前端文件流,再上传到minio。 构建一个formData的签名数据,给前端,让前端之前上传到minio。 构建一个可以上传的临时URL给前端,前端通过携带文件请求该URL进行上传。 使用filename请求服务端获取临时访问文件的URL。(最长时间为7 天,想要永久性访问,需要其他设置,这里不做说明。) 推荐,公众 号Java精选,回复java面试,获取面试资料,支持在线刷题。
下面展示页面html,使用的是VUE+element-ui进行渲染。
"UTF-8">
"stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
上传图片
"app">
"2">
"8">
"div-center-class">
"">
传统上传
class="upload-demo"
action="#"
drag
:http-request="uploadHandle">
"el-icon-upload">
"el-upload__text">将文件拖到此处,或点击上传
"el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb
"imgUrl">
"imgUrl" style="width: 40px;height: 40px">
"8">
"div-center-class">
"">
前端formData直传
class="upload-demo"
action="#"
drag
:http-request="httpRequestHandle">
"el-icon-upload">
"el-upload__text">将文件拖到此处,或点击上传
"el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb
"directUrl">
"directUrl" style="width: 40px;height: 40px">
"8">
"div-center-class">
"">
前端Url直传
class="upload-demo"
action="#"
drag
:http-request="UrlUploadHandle">
"el-icon-upload">
"el-upload__text">将文件拖到此处,或点击上传
"el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb
"uploadUrl">
"uploadUrl" style="width: 40px;height: 40px">
页面的效果就如上图所示。
可以分别体验不同的实现效果。
以上就是使用springboot搭建基于minio的高性能存储服务的全部步骤了。
本项目地址:
https://gitee.com/jack_whh/minio-upload