0%

Spring Boot集成Minio服务

/images/minio-logo.svg

在Docker中运行Minio

minio需要一个稳定的运行环境,测试的时候我们可以再docker中运行一个简单的实例,📢注意这个例子并没有映射任何volume,所以停止container的时候数据也会销毁

1
2
3
4
5
6
docker run \
-p 9000:9000 \
-p 9001:9001 \
-e "MINIO_ROOT_USER=<USERNAME>" \
-e "MINIO_ROOT_PASSWORD=<PASSWORD>" \
quay.io/minio/minio server /data --console-address ":9001"

集成到Spring boot中

在Spring boot中的pom.xml增加依赖

这里用的maven

1
2
3
4
5
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.0</version>
</dependency>

在application.properties中增加相关配置项,相关配置修改为自己的

1
2
3
4
5
6
7
8
server.port=8080
spring.servlet.multipart.max-file-size=2MB

# Minio
minio.bucket.name=minio-example-demo
minio.access.key=minioadmin
minio.access.secret=minioadmin
minio.url=https://play.min.io

配置Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration
public class MinioConfiguration {

@Value("${minio.access.key}")
private String accessKey;

@Value("${minio.access.secret}")
private String secretKey;

@Value("${minio.url}")
private String minioUrl;

@Bean
@Primary
public MinioClient minioClient() {
return new MinioClient.Builder()
.credentials(accessKey, secretKey)
.endpoint(minioUrl)
.build();
}

}

DTO,用来传输数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class FileDto implements Serializable {

private static final long serialVersionUID = 232836038145089522L;

private String title;

private String description;

@SuppressWarnings("java:S1948")
private MultipartFile file;

private String url;

private Long size;

private String filename;

}

获取文件列表

创建MinioService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Slf4j
@Service
public class MinioService {

@Autowired
private MinioClient minioClient;

@Value("${minio.bucket.name}")
private String bucketName;

public List<FileDto> getListObjects() {
List<FileDto> objects = new ArrayList<>();
try {
Iterable<Result<Item>> result = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.recursive(true)
.build());
for (Result<Item> item : result) {
objects.add(FileDto.builder()
.filename(item.get().objectName())
.size(item.get().size())
.url(getPreSignedUrl(item.get().objectName()))
.build());
}
return objects;
} catch (Exception e) {
log.error("Happened error when get list objects from minio: ", e);
}

return objects;
}

private String getPreSignedUrl(String filename) {
return "http://localhost:8080/file/".concat(filename);
}

}

创建Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Slf4j
@RestController
@RequestMapping(value = "/file")
public class FileController {

@Autowired
private MinioService minioService;

@GetMapping
public ResponseEntity<Object> getFiles() {
return ResponseEntity.ok(minioService.getListObjects());
}

}

上传文件到minio

下面代码是添加到MinioService中的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public FileDto uploadFile(FileDto request) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(request.getFile().getOriginalFilename())
.stream(request.getFile().getInputStream(), request.getFile().getSize(), -1)
.build());
} catch (Exception e) {
log.error("Happened error when upload file: ", e);
}
return FileDto.builder()
.title(request.getTitle())
.description(request.getDescription())
.size(request.getFile().getSize())
.url(getPreSignedUrl(request.getFile().getOriginalFilename()))
.filename(request.getFile().getOriginalFilename())
.build();
}

对应的Controller

1
2
3
4
@PostMapping(value = "/upload")
public ResponseEntity<Object> upload(@ModelAttribute FileDto request) {
return ResponseEntity.ok().body(minioService.uploadFile(request));
}

下载文件

添加到MinioService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public InputStream getObject(String filename) {
InputStream stream;
try {
stream = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(filename)
.build());
} catch (Exception e) {
log.error("Happened error when get list objects from minio: ", e);
return null;
}

return stream;
}

Controller

1
2
3
4
5
6
7
8
@GetMapping(value = "/**")
public ResponseEntity<Object> getFile(HttpServletRequest request) throws IOException {
String pattern = (String) request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE);
String filename = new AntPathMatcher().extractPathWithinPattern(pattern, request.getServletPath());
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(IOUtils.toByteArray(minioService.getObject(filename)));
}

访问:http://localhost:8080/file/{filename},页面中会展示或者下载对应的文件

参考