Springboot-cli 开发脚手架系列
Minio简介
- 高性能
MinIO 是全球领先的对象存储先锋,目前在全世界有数百万的用户. 在标准硬件上,读/写速度上高达183 GB / 秒 和 171 GB / 秒。
对象存储可以充当主存储层,以处理Spark、Presto、TensorFlow、H2O.ai等各种复杂工作负载以及成为Hadoop HDFS的替代品。
MinIO用作云原生应用程序的主要存储,与传统对象存储相比,云原生应用程序需要更高的吞吐量和更低的延迟。而这些都是MinIO能够达成的性能指标。 - 可扩展性
MinIO利用了Web缩放器的来之不易的知识,为对象存储带来了简单的缩放模型。 这是我们坚定的理念 “简单可扩展.” 在 MinIO, 扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。 - 云的原生支持
MinIO 是在过去4年的时间内从0开始打造的一款软件 ,符合一切原生云计算的架构和构建过程,并且包含最新的云计算的全新的技术和概念。 其中包括支持Kubernetes 、微服和多租户的的容器技术。使对象存储对于 Kubernetes更加友好。
关于minio的介绍就到这,接下来我们进行实战演示。
1. 环境配置
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- huTool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.minio/minio -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.9</version>
<!-- 避免依赖冲突 -->
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.0</version>
</dependency>
yml
配置
server:
port: 9999
minio:
endpoint: http://localhost:20000
accessKey: admin
secretKey: 12345678
secure: false
bucketName: test
2. 配置MinioClient
MinioProperties
@Data
@Component
@ConfigurationProperties(prefix = MinioProperties.PRE)
public class MinioProperties {
public static final String PRE = "minio";
/**
* endPoint是一个URL,域名,IPv4或者IPv6地址
*/
private String endpoint;
/**
* accessKey类似于用户ID,用于唯一标识你的账户
*/
private String accessKey;
/**
* secretKey是你账户的密码
*/
private String secretKey;
/**
* 如果是true,则用的是https而不是http,默认值是true
*/
private Boolean secure;
/**
* 默认存储桶
*/
private String bucketName;
@Bean
public MinioClient getMinioClient() throws Exception {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
3. 文件上传下载
MinioHandler.java
@Component
@Slf4j
@RequiredArgsConstructor
public class MinioHandler {
private final MinioClient minioClient;
private final MinioProperties minioProperties;
/**
* 判断bucket是否存在
*
* @param name 存储桶名称
*/
public boolean existBucket(String name) {
try {
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 创建存储bucket
*
* @param bucketName 存储bucket名称
*/
public boolean createdBucket(String bucketName) throws Exception {
if (!this.existBucket(bucketName)) {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
return true;
}
return false;
}
/**
* 删除存储bucket
*
* @param bucketName 存储bucket名称
*/
public boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* description: 上传文件
*
* @param file 文件
* @return: List<String> s
*/
public String saveFile(MultipartFile file) throws Exception {
if (Objects.isNull(file)) {
return "";
}
String fileName;
try {
fileName = file.getOriginalFilename();
InputStream in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(minioProperties.getBucketName())
.object(fileName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build()
);
} finally {
Optional.ofNullable(in).ifPresent(inputStream -> {
try {
inputStream.close();
} catch (IOException ignored) {
}
});
}
log.info("文件保存成功,文件名:{},类型:{}", fileName, file.getContentType());
return fileName;
}
/**
* description: 上传文件
*
* @param files 文件
* @return: List<String> s
*/
public List<String> saveFile(MultipartFile[] files) throws Exception {
List<String> names = new ArrayList<>(files.length);
for (MultipartFile file : files) {
names.add(this.saveFile(file));
}
return names;
}
/**
* 获取文件
*/
public InputStream getFile(String fileName) throws Exception {
return minioClient.getObject(GetObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build());
}
/**
* description: 下载文件
*
* @param fileName 文件名
* @return: org.springframework.http.ResponseEntity<byte [ ]>
*/
public ResponseEntity<byte[]> download(String fileName) {
return this.download(fileName, MediaType.APPLICATION_OCTET_STREAM);
}
/**
* description: 下载文件
*
* @param fileName 文件名
* @return: org.springframework.http.ResponseEntity<byte [ ]>
*/
public ResponseEntity<byte[]> download(String fileName, MediaType mediaType) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
try {
in = this.getFile(fileName);
// 封装返回值
byte[] bytes = IoUtil.readBytes(in);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
headers.setContentLength(bytes.length);
headers.setContentType(mediaType);
headers.setAccessControlExposeHeaders(List.of("*"));
responseEntity = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
Optional.ofNullable(in).ifPresent(
i -> {
try {
i.close();
} catch (IOException e) {
e.printStackTrace();
}
}
);
}
return responseEntity;
}
/**
* 查看文件对象
*
* @param bucketName 存储bucket名称
*/
public void listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
try {
for (Result<Item> result : results) {
Item item = result.get();
String s = item.objectName();
long size = item.size();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 批量删除文件对象
*
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
List<DeleteObject> dos = objects.stream().map(DeleteObject::new).collect(Collectors.toList());
return minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
}
}
4. web实战演示
- 编写
MinioController.java
文件服务api
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("minio")
public class MinioController {
private final MinioHandler minioHandler;
/**
* 创建存储桶
*/
@GetMapping("/createdBucket")
public boolean createdBucket(String bucketName) throws Exception {
return minioHandler.createdBucket(bucketName);
}
/**
* 创建存储桶
*/
@GetMapping("/removeBucket")
public boolean removeBucket(String bucketName) {
return minioHandler.removeBucket(bucketName);
}
/**
* 上传文件
*/
@PostMapping("upload")
public List<String> saveFile(MultipartFile[] files) throws Exception {
return minioHandler.saveFile(files);
}
/**
* 下载文件
*/
@GetMapping(value = "download")
public ResponseEntity<byte[]> download(String filename) {
return minioHandler.download(filename);
}
/**
* 以图片形式返回
*/
@GetMapping("get/image")
public ResponseEntity<byte[]> getImage(String filename) {
return minioHandler.download(filename, MediaType.IMAGE_JPEG);
}
}
- 以
postman
测试工具为例子测试 - 文件上传
127.0.0.1:9999/minio/upload
- 文件下载``
- 以图片的形式获取
6. 源码分享
- Springboot-cli开发脚手架,集合各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来。
- 项目源码github地址
- 项目源码国内gitee地址