Contents
@TOC
springboot+minio+docker快速入门
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
Minio提供了非常方便,友好的界面,并且文档也是非常丰富,
快速入门
环境搭建,使用docker镜像快速搭建
docker pull minio/minio
使用docker-compose.yml
1version: '3'
2services:
3 minio:
4 image: minio/minio:latest
5 container_name: minio
6 environment:
7 MINIO_ACCESS_KEY: AKIAIOSFODNN7EXAMPLE
8 MINIO_SECRET_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
9 volumes:
10 - /mnt/data:/data
11 - /mnt/config:/root/.minio
12 ports:
13 - 9000:9000
14 command: server /data
15 healthcheck:
16 test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
17 interval: 30s
18 timeout: 20s
19 retries: 3
20
1docker-compose up -d
登录管理
1http://127.0.0.1:9000/minio/login
输入 MINIO_ACCESS_KEY 和MINIO_SECRET_KEY
添加 minio
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.15.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>com.example</groupId>
12 <artifactId>minio</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>minio</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>11</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-web</artifactId>
25 </dependency>
26 <dependency>
27 <groupId>org.springframework.boot</groupId>
28 <artifactId>spring-boot-configuration-processor</artifactId>
29 </dependency>
30 <dependency>
31 <groupId>io.minio</groupId>
32 <artifactId>minio</artifactId>
33 <version>3.0.10</version>
34 </dependency>
35 <dependency>
36 <groupId>org.iherus</groupId>
37 <artifactId>qrext4j</artifactId>
38 <version>1.3.1</version>
39 </dependency>
40 <dependency>
41 <groupId>org.springframework.boot</groupId>
42 <artifactId>spring-boot-starter-test</artifactId>
43 <scope>test</scope>
44 </dependency>
45 </dependencies>
46
47 <build>
48 <plugins>
49 <plugin>
50 <groupId>org.springframework.boot</groupId>
51 <artifactId>spring-boot-maven-plugin</artifactId>
52 </plugin>
53 </plugins>
54 </build>
55
56</project>
57
配置
1
2import org.springframework.boot.context.properties.ConfigurationProperties;
3import org.springframework.stereotype.Component;
4
5/**
6 * 配置属性
7 * @author top
8 */
9@Component
10@ConfigurationProperties(prefix = "minio")
11public class MinioProperties {
12 /**
13 * 对象存储服务的URL
14 */
15 private String endpoint;
16 /**
17 * Access key就像用户ID,可以唯一标识你的账户
18 */
19 private String accessKey;
20 /**
21 * Secret key是你账户的密码
22 */
23 private String secretKey;
24
25 /**
26 * 文件桶的名称
27 */
28 private String bucketName;
29
30
31 public String getEndpoint() {
32 return endpoint;
33 }
34
35 public void setEndpoint(String endpoint) {
36 this.endpoint = endpoint;
37 }
38
39 public String getAccessKey() {
40 return accessKey;
41 }
42
43 public void setAccessKey(String accessKey) {
44 this.accessKey = accessKey;
45 }
46
47 public String getSecretKey() {
48 return secretKey;
49 }
50
51 public void setSecretKey(String secretKey) {
52 this.secretKey = secretKey;
53 }
54
55 public String getBucketName() {
56 return bucketName;
57 }
58
59 public void setBucketName(String bucketName) {
60 this.bucketName = bucketName;
61 }
62}
63
server.port=8789
#文件大小
spring.servlet.multipart.max-file-size=1024MB
spring.servlet.multipart.max-request-size=1024MB
minio.endpoint=http://192.168.0.254:9000
minio.accessKey=AKIAIOSFODNN7EXAMPLE
minio.secretKey=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
minio.bucketName=test
配置类
1
2import io.minio.MinioClient;
3import io.minio.errors.InvalidEndpointException;
4import io.minio.errors.InvalidPortException;
5import org.springframework.beans.factory.annotation.Autowired;
6import org.springframework.context.annotation.Bean;
7import org.springframework.context.annotation.Configuration;
8
9/**
10 *
11 * 配置类
12 * @author top
13 */
14@Configuration
15public class MinioConfig {
16 @Autowired
17 private MinioProperties properties;
18
19 @Bean
20 public MinioClient minioClient() {
21 MinioClient minioClient = null;
22 try {
23 minioClient = new MinioClient(properties.getEndpoint(), properties.getAccessKey(), properties.getSecretKey());
24 } catch (InvalidEndpointException | InvalidPortException e) {
25 e.printStackTrace();
26 }
27 return minioClient;
28 }
29}
30
封装一个工具,实现文件上传,下载等操作
1package com.example.minio.utils;
2
3import com.example.minio.config.MinioProperties;
4import io.minio.MinioClient;
5import io.minio.ObjectStat;
6import io.minio.Result;
7import io.minio.errors.MinioException;
8import io.minio.messages.Item;
9import org.apache.tomcat.util.http.fileupload.IOUtils;
10import org.iherus.codegen.qrcode.QrcodeConfig;
11import org.iherus.codegen.qrcode.SimpleQrcodeGenerator;
12import org.springframework.beans.factory.annotation.Autowired;
13import org.springframework.http.MediaType;
14import org.springframework.stereotype.Component;
15import org.springframework.web.multipart.MultipartFile;
16import org.xmlpull.v1.XmlPullParserException;
17
18import javax.imageio.ImageIO;
19import javax.servlet.http.HttpServletResponse;
20import java.awt.image.BufferedImage;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.net.URLEncoder;
26import java.nio.charset.StandardCharsets;
27import java.security.InvalidKeyException;
28import java.security.NoSuchAlgorithmException;
29import java.util.ArrayList;
30import java.util.List;
31import java.util.UUID;
32
33/**
34 * @author top
35 */
36@Component
37public class MinioUtils {
38
39 @Autowired
40 private MinioProperties properties;
41 @Autowired
42 private MinioClient minioClient;
43
44 /**
45 * 文件上传
46 *
47 * @param file file
48 */
49 public void upload(MultipartFile file) {
50 try {
51 // 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
52
53 // 检查存储桶是否已经存在
54 boolean isExist = minioClient.bucketExists(properties.getBucketName());
55 if (!isExist) {
56 // 创建一个名为test的存储桶,用于存储照片的zip文件。
57 minioClient.makeBucket(properties.getBucketName());
58 }
59 InputStream inputStream = file.getInputStream();
60 // 使用putObject上传一个文件到存储桶中。
61 minioClient.putObject(properties.getBucketName(), file.getOriginalFilename(), inputStream, inputStream.available(), file.getContentType());
62 //关闭
63 inputStream.close();
64 } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException | XmlPullParserException e) {
65 System.out.println("Error occurred: " + e);
66 }
67 }
68
69 /**
70 * 下载
71 *
72 * @param response response
73 * @param fileName fileName
74 */
75 public void download(HttpServletResponse response, String fileName) {
76 InputStream inputStream = null;
77 try {
78 ObjectStat stat = minioClient.statObject(properties.getBucketName(), fileName);
79 inputStream = minioClient.getObject(properties.getBucketName(), fileName);
80 response.setContentType(stat.contentType());
81 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
82 IOUtils.copy(inputStream, response.getOutputStream());
83 } catch (Exception e) {
84 e.printStackTrace();
85 } finally {
86 if (inputStream != null) {
87 try {
88 inputStream.close();
89 } catch (IOException e) {
90 e.printStackTrace();
91 }
92 }
93 }
94 }
95
96 /**
97 * 获取文件url
98 *
99 * @param objectName objectName
100 * @return url
101 */
102 public String getObject(String objectName) {
103 try {
104 return minioClient.getObjectUrl(properties.getBucketName(), objectName);
105 } catch (Exception e) {
106 e.printStackTrace();
107 }
108 return "";
109 }
110
111 /**
112 * 获取所有
113 *
114 * @return
115 */
116 public List<Album> list() {
117 try {
118 List<Album> list = new ArrayList<Album>();
119 Iterable<Result<Item>> results = minioClient.listObjects(properties.getBucketName());
120 for (Result<Item> result : results) {
121 Item item = result.get();
122 // Create a new Album Object
123 Album album = new Album();
124 System.out.println(item.objectName());
125 // Set the presigned URL in the album object
126 album.setUrl(minioClient.getObjectUrl(properties.getBucketName(), item.objectName()));
127 album.setDescription(item.objectName() + "," + item.lastModified() + ",size:" + item.size());
128 // Add the album object to the list holding Album objects
129 list.add(album);
130 }
131 return list;
132 } catch (Exception e) {
133 e.printStackTrace();
134 }
135 return null;
136 }
137
138 /**
139 * 文件删除
140 *
141 * @param name 文件名
142 */
143 public void delete(String name) {
144 try {
145 minioClient.removeObject(properties.getBucketName(), name);
146 } catch (Exception e) {
147 e.printStackTrace();
148 }
149 }
150
151 /**
152 * 上传生成的二维码
153 */
154 public void generator() {
155 String uuid = UUID.randomUUID().toString();
156 InputStream inputStream = bufferedImageToInputStream(qrcode(uuid));
157 try {
158 minioClient.putObject(properties.getBucketName(), uuid + ".png", bufferedImageToInputStream(qrcode(uuid)), inputStream.available(), MediaType.IMAGE_PNG_VALUE);
159 } catch (Exception e) {
160 e.printStackTrace();
161 } finally {
162 try {
163 if (inputStream != null) {
164 inputStream.close();
165 }
166 } catch (IOException e) {
167 e.printStackTrace();
168 }
169 }
170 }
171
172 public BufferedImage qrcode(String content) {
173 QrcodeConfig config = new QrcodeConfig()
174 .setBorderSize(2)
175 .setPadding(12)
176 .setMasterColor("#00BFFF")
177 .setLogoBorderColor("#B0C4DE")
178 .setHeight(250).setWidth(250);
179 return new SimpleQrcodeGenerator(config).setLogo("src/main/resources/logo.png").generate(content).getImage();
180 }
181
182 /**
183 * @param image image
184 * @return InputStream
185 */
186 public InputStream bufferedImageToInputStream(BufferedImage image) {
187 ByteArrayOutputStream os = new ByteArrayOutputStream();
188 try {
189 ImageIO.write(image, "png", os);
190 return new ByteArrayInputStream(os.toByteArray());
191 } catch (IOException e) {
192 e.fillInStackTrace();
193 } finally {
194 try {
195 os.close();
196 } catch (IOException e) {
197 e.printStackTrace();
198 }
199 }
200 return null;
201 }
202
203 public static class Album {
204 private String url;
205 private String description;
206
207 public String getUrl() {
208 return url;
209 }
210
211 public void setUrl(String url) {
212 this.url = url;
213 }
214
215 public String getDescription() {
216 return description;
217 }
218
219 public void setDescription(String description) {
220 this.description = description;
221 }
222 }
223}
224
controller
1
2import com.example.minio.utils.MinioUtils;
3import org.springframework.beans.factory.annotation.Autowired;
4import org.springframework.web.bind.annotation.*;
5import org.springframework.web.multipart.MultipartFile;
6
7import javax.servlet.http.HttpServletResponse;
8import java.io.UnsupportedEncodingException;
9import java.util.List;
10
11/**
12 * 文件上传下载
13 *
14 * @author top
15 */
16@RestController
17public class MinioController {
18 @Autowired
19 private MinioUtils minioUtils;
20
21 @PostMapping(value = "/upload")
22 public void upload(@RequestParam("file") MultipartFile file) {
23 minioUtils.upload(file);
24 }
25
26 @GetMapping(value = "/download")
27 public void download(HttpServletResponse response, @RequestParam(value = "fileName") String fileName) throws UnsupportedEncodingException {
28 minioUtils.download(response, fileName);
29 }
30
31 @GetMapping(value = "/list")
32 public List<MinioUtils.Album> list() {
33 return minioUtils.list();
34 }
35
36 @GetMapping(value = "/objectName")
37 public String getObject(@RequestParam(value = "fileName") String fileName) {
38 return minioUtils.getObject(fileName);
39 }
40
41 @DeleteMapping(value = "/delete/{name}")
42 public void delete(@PathVariable String name) {
43 minioUtils.delete(name);
44 }
45}
46
总结
完成了一个入门的案例,遇到问题可多看看参考文档。
个人博客地址