Minio

安装minio

启动docker

1
docker pull minio/minio

启动

1
2
3
4
5
6
7
8
docker run -p 9000:9000 -p 9090:9090 \
--name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=minio" \
-e "MINIO_SECRET_KEY=minio" \
-v /usr/minio/:/data \
minio/minio server \
/data --console-address ":9090" -address ":9000"

浏览器访问api为9090端口,JavaAPI访问是9000端口

报错

解决Mockito警告:Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK.

1
io.minio.errors.InvalidResponseException: Non-XML response from server. Response code: 400, Content-Type: text/xml; charset=utf-8, body: <?xml version="1.0" encoding="UTF-8"?><Error><Code>InvalidArgument</Code><Message>S3 API Requests must be made to API port.</Message><RequestId>0</RequestId></Error>

解决方法

在依赖中加入

1
2
3
4
5
6
7
8
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
<configuration>
<argLine>-javaagent:"${settings.localRepository}/org/mockito/mockito-core/5.14.2/mockito-core-5.14.2.jar"</argLine>
</configuration>
</plugin>

刷新即可

报错

1
io.minio.errors.InvalidResponseException: Non-XML response from server. Response code: 400, Content-Type: text/xml; charset=utf-8, body: <?xml version="1.0" encoding="UTF-8"?><Error><Code>InvalidArgument</Code><Message>S3 API Requests must be made to API port.</Message><RequestId>0</RequestId></Error>

是由于端口使用错误,应该使用api端口,也就是9000端口

报错时间错误

在linux上校准时间

1
yum install ntpdate -y

执行

1
ntpdate pool.ntp.org

查看时间

1
date

在Java中使用api控制

在pom文件中导入依赖

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

建立properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.minio.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;


@Component
@Data
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;

}

建立config

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
package com.example.minio.config;


import com.example.minio.properties.MinioProperties;
import com.example.minio.utils.MinioUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class MinioConfig {
@Bean
@ConditionalOnMissingBean
public MinioUtils minioUtils(MinioProperties minioProperties) {
log.info("开始创建工具类对象:{}", minioProperties);
return new MinioUtils(minioProperties.getEndpoint(),
minioProperties.getAccessKey(),
minioProperties.getSecretKey(),
minioProperties.getBucketName());
}
}


建立utils

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
38
39
package com.example.minio.utils;

import com.example.minio.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;



@Slf4j
@AllArgsConstructor
@Data
public class MinioUtils {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;

public String upload(String objectName, InputStream inputStream) {
try {
MinioClient minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build());
log.info("上传文件成功");
String URL = endpoint + "/" + bucketName + "/" + objectName;
return URL;
}catch (Exception e) {
log.error("上传文件失败");
e.printStackTrace();
}
return null;

}


}

建立controller

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
package com.example.minio.Controller;

import com.example.minio.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.UUID;

@RestController
public class Controller {
@Autowired
private MinioUtils minioUtils;

@PostMapping("/upload")
public String updateFile(@RequestParam("file") MultipartFile inputStream) throws Exception {
UUID uuid = UUID.randomUUID();
String objectName = uuid.toString();
String originalFilename = inputStream.getOriginalFilename();
objectName = objectName+originalFilename.substring(originalFilename.lastIndexOf("."));
String url = minioUtils.upload(objectName, inputStream.getInputStream());
return url;
}
}

pom依赖

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>minio</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>minio</name>
<description>minio</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.11</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

config文件中的解释

这段代码的主要功能是配置并注册一个MinioUtils Bean到Spring的上下文中。MinioUtils是一个工具类,用于与MinIO对象存储进行交互。通过使用@ConditionalOnMissingBean注解,确保了在Spring容器中只有一个MinioUtils实例。同时,通过自动注入MinioProperties对象,代码可以从配置文件中读取MinIO的相关配置信息并初始化MinioUtils对象。这使得应用程序可以方便地与MinIO进行集成和操作。

api测试接口

image-20250127210637768

文件结构

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
│  mvnw
│ mvnw.cmd
│ pom.xml
│ tree.txt

├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─example
│ │ │ └─minio
│ │ │ │ MinioApplication.java
│ │ │ │
│ │ │ ├─config
│ │ │ │ MinioConfig.java
│ │ │ │
│ │ │ ├─Controller
│ │ │ │ Controller.java
│ │ │ │
│ │ │ ├─properties
│ │ │ │ MinioProperties.java
│ │ │ │
│ │ │ └─utils
│ │ │ MinioUtils.java


测试

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@SpringBootTest
class DemoApplicationTests {
@Autowired
private service service;
@Autowired
private MinioClient minioClient;

@Test
void contextLoads() {
service.testMinio();
}

/*测试是否存在某个bucket*/
@Test
void testMinio() throws Exception {
boolean file = minioClient.bucketExists(BucketExistsArgs.builder().bucket("file").build());
System.out.println(file);
}

/*创建bucket*/
@Test
void test2() throws Exception {
boolean file = minioClient.bucketExists(BucketExistsArgs.builder().bucket("file").build());
if (!file) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket("file").build());
} else {
System.out.println("bucket已经存在");
}

}

/*列出所有bucket*/
@Test
void test3() throws Exception {
List<Bucket> buckets = minioClient.listBuckets();
for (Bucket bucket : buckets) {
System.out.println(bucket.name() + "---" + bucket.creationDate());
}
}

/*删除bucket*/
@Test
void test4() throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket("file").build());
}

//插入图片
@Test
void test5() throws Exception {
File file = new File("C:\\Users\\DREAMXIAOSHEN\\Downloads\\bc.png");
minioClient.putObject(PutObjectArgs.builder()
.bucket("file")
.object("first.jpg")
.stream(new FileInputStream(file), file.length(), -1)
.build());


}

/*判断文件是否存在*/
@Test
void test6() throws Exception {
StatObjectResponse file = minioClient.statObject(StatObjectArgs.builder().
bucket("file").object("first.jpg").build()
);
System.out.println(file);
}