从零开始学YC-Framework之文件服务(MinIO)

文件存储与访问对于任何一个IT系统,都是必不可少的。

YC-Framework针对这样的情况,也提供一套解决方案,解决方案包含Nginx代理服务器方式、MinIO等。

Nginx代理服务器的方式,基于本地文件存储,文件存储的地方为对应服务器的磁盘空间上,然后通过Nginx代理进行访问。

关于Nginx相关实战系列文章,可以参考我写的这篇文章深入理解Nginx,该文章记录了Nginx常用的实战操作策略。

下面开始着重介绍,YC-Framework基于MinIO的分布式文件存储方案实践。

一、什么是MinIO?

MinIO是在GNU Affero通用公共许可证v3.0下发布的高性能对象存储。它与 Amazon S3云存储服务API兼容。使用MinIO为机器学习、分析和应用程序数据工作负载构建高性能基础架构。

二、MinIO的相关资料有哪些(强烈建议以官网为主,博客参考为辅)?

官方网站:
https://min.io/

官方文档:
https://docs.min.io/?ref=con

SDK使用文档:
https://docs.min.io/docs/java-client-quickstart-guide.html

三、在Linux上如何安装?

很简单一共四步:

1
2
3
4
5
6
7
8
9
10
11
# Download
wget https://dl.min.io/server/minio/release/linux-amd64/minio

# Authorization
chmod +x minio

# Run
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=minio_admin ./minio server /mnt/data --console-address "0.0.0.0:21218"

# Backup Run
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=minio_admin nohup ./minio server /mnt/data --console-address "0.0.0.0:21218" &

Windows安装更简单,这里不再赘述,大家可以参考官方文档!!!

四、在Java项目中如何使用MinIO?

1.引入Maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<properties>
<minio.version>8.4.1</minio.version>
<okhttp.version>4.8.1</okhttp.version>
</properties>

<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>

2.配置类

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class MinIOConfig {

@Bean
public MinioClient minioClient() {
MinioClient minioClient = MinioClient.builder().endpoint("http://127.0.0.1:9000")
.credentials("minioadmin", "minioadmin") //minIO默认用户名和密码,上生产一定要更改
.build();

return minioClient;
}
}

3.工具类

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

@Component
public class MinioUtil {


private static final String MINIO_BUCKET = "yc-framework";

@Autowired
private MinioClient minioClient;

/**
* 查看存储bucket是否存在
*
* @return boolean
*/
public Boolean bucketExists(String bucketName) {
Boolean found;
try {
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return found;
}

/**
* 创建存储bucket
*
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}

/**
* 删除存储bucket
*
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}

/**
* 获取全部bucket
*/
public List<Bucket> getAllBuckets() {
try {
List<Bucket> buckets = minioClient.listBuckets();
return buckets;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}


/**
* 文件上传
*
* @param file 文件
* @return Boolean
*/
public String upload(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
if (StrUtil.isBlank(originalFilename)) {
throw new RuntimeException();
}
String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = IdUtil.simpleUUID() + "_" + fileName;
System.out.println("objectName:" + objectName);
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(MINIO_BUCKET).object(objectName)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
//文件名称相同会覆盖
minioClient.putObject(objectArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectName;
}

/**
* 预览图片
*
* @param fileName
* @return
*/
public String preview(String fileName) {
// 查看文件地址
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(MINIO_BUCKET).object(fileName).method(Method.GET).build();
try {
String url = minioClient.getPresignedObjectUrl(build);
return url;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 文件下载
*
* @param fileName 文件名称
* @param res response
* @return Boolean
*/
public void download(String fileName, HttpServletResponse res) {
GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(MINIO_BUCKET)
.object(fileName).build();
try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
byte[] buf = new byte[1024];
int len;
try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
while ((len = response.read(buf)) != -1) {
os.write(buf, 0, len);
}
os.flush();
byte[] bytes = os.toByteArray();
res.setCharacterEncoding("utf-8");
// 设置强制下载不打开
// res.setContentType("application/force-download");
res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
try (ServletOutputStream stream = res.getOutputStream()) {
stream.write(bytes);
stream.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 查看文件对象
*
* @return 存储bucket内文件对象信息
*/
public List<Item> listObjects() {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(MINIO_BUCKET).build());
List<Item> items = new ArrayList<>();
try {
for (Result<Item> result : results) {
items.add(result.get());
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return items;
}

/**
* 删除
*
* @param fileName
* @return
* @throws Exception
*/
public boolean remove(String fileName) {
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(MINIO_BUCKET).object(fileName).build());
} catch (Exception e) {
return false;
}
return true;
}

}

4.核心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
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
70
71
72
73
@RestController
@Api(tags = {"基于MinIO对象存储"}, description = "基于MinIO对象存储")
public class MinIOController {
@Autowired
private MinioUtil minioUtil;

@GetMapping("/bucketExists")
@ApiOperation(value = "查看存储bucket是否存在")
public RespBody bucketExists(String bucketName) {
return RespBody.success(minioUtil.bucketExists(bucketName));
}


@GetMapping("/makeBucket")
@ApiOperation(value = "创建存储bucket")
public RespBody makeBucket(String bucketName) {
minioUtil.makeBucket(bucketName);
return RespBody.success();
}


@GetMapping("/removeBucket")
@ApiOperation(value = "删除存储bucket")
public RespBody removeBucket(String bucketName) {
minioUtil.removeBucket(bucketName);
return RespBody.success();
}


@GetMapping("/getAllBuckets")
@ApiOperation(value = "获取全部bucket")
public RespBody<List<Bucket>> getAllBuckets() {
List<Bucket> allBuckets = minioUtil.getAllBuckets();
return RespBody.success(allBuckets);
}


@PostMapping("/upload")
@ApiOperation(value = "文件上传返回url")
public RespBody<String> upload(@RequestParam(value = "file") MultipartFile file) {
String objectName = minioUtil.upload(file);
if (null != objectName) {
String endPoint = "http://127.0.0.1:9000";
return RespBody.success(endPoint + "/" + objectName);
}
return RespBody.fail();
}


@GetMapping("/preview")
@ApiOperation(value = "图片/视频预览")
public RespBody preview(@RequestParam("fileName") String fileName) {
return RespBody.success(minioUtil.preview(fileName));
}


@GetMapping("/download")
@ApiOperation(value = "文件下载")
public RespBody download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
minioUtil.download(fileName, res);
return RespBody.success();
}


@PostMapping("/delete")
@ApiOperation(value = "删除文件", notes = "根据url地址删除文件")
public RespBody remove(String url) {
String objName = url.substring(url.lastIndexOf("test" + "/") + "test".length() + 1);
minioUtil.remove(objName);
return RespBody.success();
}

}

5.启动yc-file微服务进行测试

(1)上传

图一

(2)预览

图二

图二

源代码均已开源,开源不易,如果对你有帮助,不妨给个star!!!

YC-Framework官网:
https://framework.youcongtech.com/

YC-Framework Github源代码:
https://github.com/developers-youcong/yc-framework

YC-Framework Gitee源代码:
https://gitee.com/developers-youcong/yc-framework

文章目录
  1. 一、什么是MinIO?
  2. 二、MinIO的相关资料有哪些(强烈建议以官网为主,博客参考为辅)?
  3. 三、在Linux上如何安装?
  4. 四、在Java项目中如何使用MinIO?
    1. 1.引入Maven依赖
    2. 2.配置类
    3. 3.工具类
    4. 4.核心Controller代码
    5. 5.启动yc-file微服务进行测试
      1. (1)上传
      2. (2)预览