aa72ced8 by 蔡永松

Minio服务集成

1 parent 6b9b1868
...@@ -366,7 +366,7 @@ ...@@ -366,7 +366,7 @@
366 </profiles> 366 </profiles>
367 367
368 <properties> 368 <properties>
369 <oracle.version>11.2.0.4</oracle.version> 369 <oracle.version>11.2.0.3</oracle.version>
370 <geotools.version>24-SNAPSHOT</geotools.version> 370 <geotools.version>24-SNAPSHOT</geotools.version>
371 <org.springframework.version>5.1.8.RELEASE</org.springframework.version> 371 <org.springframework.version>5.1.8.RELEASE</org.springframework.version>
372 <org.spring.boot.version>2.1.8.RELEASE</org.spring.boot.version> 372 <org.spring.boot.version>2.1.8.RELEASE</org.spring.boot.version>
......
1 package com.pashanhoo.common.minio;
2
3 import io.minio.*;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.stereotype.Component;
8 import org.springframework.web.multipart.MultipartFile;
9
10 import java.io.ByteArrayInputStream;
11 import java.io.InputStream;
12 import java.util.Date;
13
14 /**
15 * @author CAIYONGSONG
16 * @commpany www.pashanhoo.com
17 * @date 2022/7/20
18 */
19 @Component
20 public class FileServerOptUtil {
21 private Logger log = LoggerFactory.getLogger(FileServerOptUtil.class);
22
23 @Autowired
24 MinioClient minioClient;
25
26 /**
27 * 获取桶中某个对象的输入流
28 * @param bucketName
29 * @param path
30 * @return
31 */
32 public InputStream getObjectInputStream(String bucketName, String path){
33 log.info("从桶:" + bucketName + ",获取:" + path + "对象流!");
34 InputStream stream = null;
35 try {
36 stream = minioClient.getObject(
37 GetObjectArgs.builder().bucket(bucketName).object(path).build());
38 } catch (Exception e) {
39 log.error("从桶:" + bucketName + ",获取:" + path + "对象流错误!");
40 e.printStackTrace();
41 }
42 return stream;
43 }
44
45 /**
46 *
47 * @param bucketName
48 * @param dirPath 如:path/to/
49 * @return
50 */
51 public boolean mkdir(String bucketName,String dirPath){
52 log.info("在桶:" + bucketName + ",中创建:" + dirPath);
53 boolean result = false;
54 try {
55 minioClient.putObject(
56 PutObjectArgs.builder().bucket(bucketName).object(dirPath).stream(
57 new ByteArrayInputStream(new byte[] {}), 0, -1)
58 .build());
59 result = true;
60 } catch (Exception e) {
61 log.error("在桶:" + bucketName + ",中创建:" + dirPath + "错误!");
62 e.printStackTrace();
63 }
64 return result;
65 }
66
67
68 /**
69 * 往对象存储服务目标桶的目标位置上传文件
70 * @param bucketName 桶
71 * @param toPath 目标位置如:test/2.txt
72 * @param fromPath 本地文件位置
73 * @return
74 */
75 public boolean uploadObject(String bucketName,String toPath,String fromPath ){
76 log.info("从本地:" + fromPath + "往桶:" + bucketName + ",中上传文件:" + toPath);
77 boolean result = false;
78 try {
79 minioClient.uploadObject(
80 UploadObjectArgs.builder()
81 .bucket(bucketName)
82 .object(toPath)
83 .filename(fromPath)
84 .build());
85 result = true;
86 } catch (Exception e) {
87 log.error("从本地:" + fromPath + "往桶:" + bucketName + ",中上传文件:" + toPath + "错误!");
88 e.printStackTrace();
89 }
90 return result;
91 }
92
93
94 /**
95 * 从桶中下载文件到本地文件
96 * @param bucketName
97 * @param fromPath
98 * @param toPath
99 * @return
100 */
101 public boolean downloadFile(String bucketName,String fromPath,String toPath){
102 log.info("从桶:" + bucketName + "中将" + fromPath + "文件下载到:" + toPath);
103 boolean result = false;
104 try {
105 minioClient.downloadObject(
106 DownloadObjectArgs.builder()
107 .bucket(bucketName)
108 .object(fromPath)
109 .filename(toPath)
110 .build());
111 result = true;
112 } catch (Exception e) {
113 log.error("从桶:" + bucketName + "中将" + fromPath + "文件下载到:" + toPath + "错误!");
114 e.printStackTrace();
115 }
116 return result;
117 }
118 public static String extractFilename(MultipartFile file){
119 if (file.isEmpty()) {
120 throw new RuntimeException("文件不存在!");
121 }
122 return DateUtils.dateToStr(new Date()) + "/" + System.currentTimeMillis() + "_" + file.getOriginalFilename() ;
123
124 }
125 }
...\ No newline at end of file ...\ No newline at end of file
1 package com.pashanhoo.common.minio;
2
3 import io.minio.MinioClient;
4 import lombok.Data;
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7 import org.springframework.boot.context.properties.ConfigurationProperties;
8 import org.springframework.context.annotation.Bean;
9 import org.springframework.stereotype.Component;
10
11 /**
12 * @author CAIYONGSONG
13 * @commpany www.pashanhoo.com
14 * @date 2022/7/20
15 */
16 @Data
17 @Component
18 @ConfigurationProperties(prefix = "minio")
19 public class MinioConfig {
20 private Logger log = LoggerFactory.getLogger(MinioConfig.class);
21
22 // minio地址
23 private String minioUrl;
24 //minio账号
25 private String accessKey;
26 //minio密码
27 private String secretKey;
28 //存储桶名称 */
29 public String bucketName;
30 // "如果是true,则用的是https而不是http,默认值是true"
31 public static Boolean secure = false;
32
33
34 @Bean
35 public MinioClient getMinioClient(){
36 log.info("初始化MinioClient客户端:minioUrl:" + minioUrl + ",accessKey:" + accessKey + ",secretKey:" + secretKey);
37 MinioClient minioClient = MinioClient.builder()
38 .endpoint(minioUrl)
39 .credentials(accessKey,secretKey)
40 .build();
41 return minioClient;
42 }
43
44 }
1 package com.pashanhoo.common.minio;
2
3 import io.minio.*;
4 import io.minio.messages.DeleteError;
5 import io.minio.messages.DeleteObject;
6 import io.minio.messages.Item;
7 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.stereotype.Component;
9 import org.springframework.util.FastByteArrayOutputStream;
10 import org.springframework.web.multipart.MultipartFile;
11
12 import javax.servlet.ServletOutputStream;
13 import javax.servlet.http.HttpServletResponse;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.stream.Collectors;
17
18 /**
19 * @author CAIYONGSONG
20 * @commpany www.pashanhoo.com
21 * @date 2022/7/20
22 */
23
24 @Component
25 public class MinioUtil {
26
27 @Autowired
28 private MinioClient minioClient;
29
30 /**
31 * 查看存储bucket是否存在
32 *
33 * @param bucketName 存储bucket
34 * @return boolean
35 */
36 public Boolean bucketExists(String bucketName) {
37 Boolean found;
38 try {
39 found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
40 } catch (Exception e) {
41 e.printStackTrace();
42 return false;
43 }
44 return found;
45 }
46
47 /**
48 * 创建存储bucket
49 *
50 * @param bucketName 存储bucket名称
51 * @return Boolean
52 */
53 public Boolean makeBucket(String bucketName) {
54 try {
55 minioClient.makeBucket(MakeBucketArgs.builder()
56 .bucket(bucketName)
57 .build());
58 } catch (Exception e) {
59 e.printStackTrace();
60 return false;
61 }
62 return true;
63 }
64
65 /**
66 * 删除存储bucket
67 *
68 * @param bucketName 存储bucket名称
69 * @return Boolean
70 */
71 public Boolean removeBucket(String bucketName) {
72 try {
73 minioClient.removeBucket(RemoveBucketArgs.builder()
74 .bucket(bucketName)
75 .build());
76 } catch (Exception e) {
77 e.printStackTrace();
78 return false;
79 }
80 return true;
81 }
82
83 /**
84 * 文件上传
85 *
86 * @param file 文件
87 * @param bucketName 存储bucket
88 * @return Boolean
89 */
90 public Boolean upload(MultipartFile file, String fileName, String bucketName) {
91 try {
92 PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
93 .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
94 //文件名称相同会覆盖
95 minioClient.putObject(objectArgs);
96 } catch (Exception e) {
97 e.printStackTrace();
98 return false;
99 }
100 return true;
101 }
102
103 /**
104 * 文件下载
105 *
106 * @param bucketName 存储bucket名称
107 * @param fileName 文件名称
108 * @param res response
109 * @return Boolean
110 */
111 public void download(String bucketName, String fileName, HttpServletResponse res) {
112 GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
113 .object(fileName).build();
114 try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
115 byte[] buf = new byte[1024];
116 int len;
117 try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
118 while ((len = response.read(buf)) != -1) {
119 os.write(buf, 0, len);
120 }
121 os.flush();
122 byte[] bytes = os.toByteArray();
123 res.setCharacterEncoding("utf-8");
124 //设置强制下载不打开
125 res.setContentType("application/force-download");
126 res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
127 try (ServletOutputStream stream = res.getOutputStream()) {
128 stream.write(bytes);
129 stream.flush();
130 }
131 }
132 } catch (Exception e) {
133 e.printStackTrace();
134 }
135 }
136
137 /**
138 * 查看文件对象
139 *
140 * @param bucketName 存储bucket名称
141 * @return 存储bucket内文件对象信息
142 */
143 public List<ObjectItem> listObjects(String bucketName) {
144 Iterable<Result<Item>> results = minioClient.listObjects(
145 ListObjectsArgs.builder().bucket(bucketName).build());
146 List<ObjectItem> objectItems = new ArrayList<>();
147 try {
148 for (Result<Item> result : results) {
149 Item item = result.get();
150 ObjectItem objectItem = new ObjectItem();
151 objectItem.setObjectName(item.objectName());
152 objectItem.setSize(item.size());
153 objectItems.add(objectItem);
154 }
155 } catch (Exception e) {
156 e.printStackTrace();
157 return null;
158 }
159 return objectItems;
160 }
161
162 /**
163 * 批量删除文件对象
164 *
165 * @param bucketName 存储bucket名称
166 * @param objects 对象名称集合
167 */
168 public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
169 List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
170 Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
171 return results;
172 }
173
174 }
1 package com.pashanhoo.common.minio;
2
3 import io.swagger.annotations.ApiModel;
4
5 /**
6 * @author CAIYONGSONG
7 * @commpany www.pashanhoo.com
8 * @date 2022/7/20
9 */
10 @ApiModel("用户实体类")
11 public class ObjectItem {
12
13 long size;
14 String objectName;
15
16 public long getSize() {
17 return size;
18 }
19
20 public void setSize(long size) {
21 this.size = size;
22 }
23
24 public String getObjectName() {
25 return objectName;
26 }
27
28 public void setObjectName(String objectName) {
29 this.objectName = objectName;
30 }
31 }
1 package com.pashanhoo.config;
2
3 import lombok.extern.slf4j.Slf4j;
4 import org.springframework.context.annotation.Bean;
5 import org.springframework.context.annotation.Configuration;
6 import org.springframework.web.client.RestTemplate;
7
8 /**
9 * @author CAIYONGSONG
10 * @commpany www.pashanhoo.com
11 * @date 2022/8/18
12 */
13 @Configuration
14 @Slf4j
15 public class TestTemplateBeanConfig {
16 @Bean
17 RestTemplate restTemplate(){
18 log.info("完成初始化RestTemplate得bean");
19 return new RestTemplate();
20 }
21 }
1 package com.pashanhoo.qys.controller;
2
3
4 import com.pashanhoo.common.Result;
5 import com.pashanhoo.qys.service.SysFileService;
6 import io.minio.GetObjectArgs;
7 import io.minio.ListObjectsArgs;
8 import io.minio.MinioClient;
9 import io.minio.messages.Item;
10 import io.swagger.annotations.Api;
11 import io.swagger.annotations.ApiOperation;
12 import org.apache.tomcat.util.http.fileupload.IOUtils;
13 import org.springframework.beans.factory.annotation.Autowired;
14 import org.springframework.http.MediaType;
15 import org.springframework.util.StringUtils;
16 import org.springframework.web.bind.annotation.*;
17 import org.springframework.web.multipart.MultipartFile;
18
19 import javax.servlet.http.HttpServletResponse;
20 import java.io.BufferedOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URLEncoder;
24
25 /**
26 * @author CAIYONGSONG
27 * @commpany www.pashanhoo.com
28 * @date 2022/7/20
29 */
30
31 @Api(tags = "Minio文件上传")
32 @RestController
33 @RequestMapping("/system/file")
34 public class SysFileController {
35
36 @Autowired
37 private SysFileService sysFileService;
38
39 @Autowired
40 private MinioClient minioClient;
41
42 /**
43 * 图片上传minio
44 *
45 * @param file 图片文件
46 * @return 返回
47 */
48 @ApiOperation("点选文件-文件上传")
49 @RequestMapping(value = "/upload", method = RequestMethod.POST)
50 public Result uploadFileMinio(MultipartFile file) {
51 String url = sysFileService.uploadFileMinio(file);
52 if (!StringUtils.isEmpty(url)) {
53 return Result.ok(url);
54 }
55 return Result.error(-1,"上传失败");
56 }
57
58 @PostMapping(value = "/upload-files" )
59 @ApiOperation(value = "文件上传(支持批量)", notes = "文件上传(支持批量)")
60 public Result uploadFiles(@RequestPart MultipartFile[] files ) throws IOException {
61 String url = sysFileService.uploadFileMinio(files);
62 if (!StringUtils.isEmpty(url)) {
63 return Result.ok(url);
64 }
65 return Result.error(-1,"上传失败");
66 }
67
68 // 暂未实现
69 @ApiOperation("文件下载")
70 @RequestMapping(value = "/download", method = RequestMethod.POST)
71 public String download(HttpServletResponse response) {
72 try {
73 Iterable<io.minio.Result<Item>> results = minioClient.listObjects(
74 ListObjectsArgs.builder().bucket("eci-bucket").build()//获取bucket里所有文件信息
75 );
76 String fileName = null;
77 for (io.minio.Result<Item> result : results) {
78 Item item = result.get();
79 fileName = item.objectName();
80 System.out.println(item.lastModified() + "\t" + item.size() + "\t" + item.objectName());
81 }
82
83 InputStream object = minioClient.getObject(GetObjectArgs.builder().bucket("eci-bucket").object(fileName).build());
84 BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
85 IOUtils.copy(object, bos);
86 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
87 response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
88 bos.flush();
89 return "success";
90 } catch (Exception e) {
91 e.printStackTrace();
92 return e.getMessage();
93 }
94 }
95
96 }
...\ No newline at end of file ...\ No newline at end of file
1 package com.pashanhoo.qys.service;
2
3 import org.springframework.web.multipart.MultipartFile;
4
5 /**
6 * @author CAIYONGSONG
7 * @commpany www.pashanhoo.com
8 * @date 2022/7/20
9 */
10 public interface SysFileService {
11
12 public String uploadFileMinio(MultipartFile file);
13 public String uploadFileMinio(MultipartFile[] file);
14 }
1 package com.pashanhoo.qys.service.impl;
2
3 import com.pashanhoo.common.minio.FileServerOptUtil;
4 import com.pashanhoo.common.minio.MinioConfig;
5 import com.pashanhoo.common.minio.MinioUtil;
6 import com.pashanhoo.qys.service.SysFileService;
7 import lombok.extern.slf4j.Slf4j;
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Service;
10 import org.springframework.web.multipart.MultipartFile;
11
12 /**
13 * @author CAIYONGSONG
14 * @commpany www.pashanhoo.com
15 * @date 2022/7/20
16 */
17 @Service
18 @Slf4j
19 public class SysFileServiceImpl implements SysFileService {
20
21 @Autowired
22 private MinioConfig minioConfig;
23
24 @Autowired
25 private MinioUtil minioUtil;
26
27 @Override
28 public String uploadFileMinio(MultipartFile[] files){
29 Long st = System.currentTimeMillis();
30 log.info("开始上传批量文件" + files.length);
31 // 判断存储桶是否存在
32 if (!minioUtil.bucketExists(minioConfig.getBucketName())) {
33 minioUtil.makeBucket(minioConfig.getBucketName());
34 }
35 StringBuilder sbf = new StringBuilder();
36 for (MultipartFile file : files) {
37 if (file.isEmpty()) {
38 throw new RuntimeException("文件不存在!");
39 }
40 log.info("循环开始上传单个文件,文件大小:" + file.getSize());
41
42 // 生成文件名 按照要求-带文件夹路径的文件的全路径
43 String fineName = FileServerOptUtil.extractFilename(file);
44 try {
45 // 上传文件
46 minioUtil.upload(file, fineName, minioConfig.getBucketName());
47 } catch (Exception e) {
48 System.out.println("上传minio服务器期出错了 " + e.getMessage());
49 e.printStackTrace();
50 return null;
51 }
52 sbf.append(minioConfig.getMinioUrl()).append("/").append( minioConfig.getBucketName())
53 .append("/").append(fineName).append(",");
54 }
55 //String url = minioConfig.getMinioUrl() + "/" + minioConfig.getBucketName() + "/" + fineName;
56 String resUrl = sbf.toString().substring(0,(sbf.length()-1));
57 log.info("上传文件结束,总耗时:"+(System.currentTimeMillis() - st) +"s, 文件路径:" + resUrl );
58 return resUrl;
59
60 }
61
62 @Override
63 public String uploadFileMinio(MultipartFile file) {
64 Long st = System.currentTimeMillis();
65 if (file.isEmpty()) {
66 throw new RuntimeException("文件不存在!");
67 }
68 log.info("开始上传单个文件,文件大小:" + (file.getSize()/1024) + "KB");
69 // 判断存储桶是否存在
70 if (!minioUtil.bucketExists(minioConfig.getBucketName())) {
71 minioUtil.makeBucket(minioConfig.getBucketName());
72 }
73 // 生成文件名 按照要求-带文件夹路径的文件的全路径
74 String fineName = FileServerOptUtil.extractFilename(file);
75 try {
76 // 上传文件
77 minioUtil.upload(file, fineName, minioConfig.getBucketName());
78 } catch (Exception e) {
79 System.out.println("上传minio服务器期出错了 " + e.getMessage());
80 e.printStackTrace();
81 return null;
82 }
83
84 String url = minioConfig.getMinioUrl() + "/" + minioConfig.getBucketName() + "/" + fineName;
85
86 log.info("上传文件结束,总耗时:"+(System.currentTimeMillis() - st) +"ms, 文件路径:" + url );
87 return url;
88
89 }
90 }
...\ No newline at end of file ...\ No newline at end of file
...@@ -7,8 +7,8 @@ server: ...@@ -7,8 +7,8 @@ server:
7 spring: 7 spring:
8 servlet: 8 servlet:
9 multipart: 9 multipart:
10 maxFileSize: 10MB 10 maxFileSize: 100MB
11 maxRequestSize: 10MB 11 maxRequestSize: 500MB
12 application: 12 application:
13 name: hzbdcsyn 13 name: hzbdcsyn
14 jackson: 14 jackson:
...@@ -71,5 +71,16 @@ management: ...@@ -71,5 +71,16 @@ management:
71 71
72 logging: 72 logging:
73 config: "classpath:logback-spring.xml" 73 config: "classpath:logback-spring.xml"
74 74 # Minio配置
75 minio:
76 # minio配置的地址,端口9000
77 minioUrl: http://172.16.56.30:90
78 # 账号
79 accessKey: minioadmin
80 # 密码
81 secretKey: minioadmin
82 # MinIO桶名字
83 bucketName: ecibucket
84 swagger2:
85 enable: false
75 86
......
...@@ -7,8 +7,8 @@ server: ...@@ -7,8 +7,8 @@ server:
7 spring: 7 spring:
8 servlet: 8 servlet:
9 multipart: 9 multipart:
10 maxFileSize: 10MB 10 maxFileSize: 100MB
11 maxRequestSize: 10MB 11 maxRequestSize: 500MB
12 application: 12 application:
13 name: hzbdcsyn 13 name: hzbdcsyn
14 jackson: 14 jackson:
...@@ -71,5 +71,16 @@ management: ...@@ -71,5 +71,16 @@ management:
71 71
72 logging: 72 logging:
73 config: "classpath:logback-spring.xml" 73 config: "classpath:logback-spring.xml"
74 74 # Minio配置
75 minio:
76 # minio配置的地址,端口9000
77 minioUrl: http://172.16.56.30:90
78 # 账号
79 accessKey: minioadmin
80 # 密码
81 secretKey: minioadmin
82 # MinIO桶名字
83 bucketName: ecibucket
84 swagger2:
85 enable: true
75 86
......
1 spring: 1 spring:
2 profiles: 2 profiles:
3 active: dev 3 active: test
......