Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
S
springboot-minio-demo
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
yifu-study
yifu-temp
springboot-minio-demo
Commits
ad797d81
Commit
ad797d81
authored
Apr 11, 2022
by
licancan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
minio测试demo
parents
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1246 additions
and
0 deletions
+1246
-0
README.md
README.md
+10
-0
minio部署使用.md
minio部署使用.md
+480
-0
pom.xml
pom.xml
+128
-0
Application.java
src/main/java/com/yifu/minio/Application.java
+16
-0
Swagger2.java
src/main/java/com/yifu/minio/Swagger2.java
+39
-0
CorsConfig.java
src/main/java/com/yifu/minio/config/CorsConfig.java
+36
-0
MinioConfig.java
src/main/java/com/yifu/minio/config/MinioConfig.java
+28
-0
FileController.java
src/main/java/com/yifu/minio/controller/FileController.java
+89
-0
AjaxResult.java
src/main/java/com/yifu/minio/domain/AjaxResult.java
+178
-0
FileInfo.java
src/main/java/com/yifu/minio/domain/FileInfo.java
+28
-0
MinioUtil.java
src/main/java/com/yifu/minio/util/MinioUtil.java
+98
-0
application.yml
src/main/resources/application.yml
+18
-0
log4j2.xml
src/main/resources/log4j2.xml
+98
-0
No files found.
README.md
0 → 100644
View file @
ad797d81
# springboot-minio
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。 本项目集成Minio的java客户端SDK,对Minio文件服务器进行读写,将操作封装为MinioUtil工具,直接在项目中可以复用。其操作主要包括:
-
上传文件
-
下载文件
-
读取桶列表
-
读取桶中的文件列表
-
删除桶
-
删除文件
\ No newline at end of file
minio部署使用.md
0 → 100644
View file @
ad797d81
# minio部署及使用
minio文档地址:https://docs.min.io/docs/
>注意 部署的时候参考官方文档,在网上找的教程 部署可能会出问题
1.
docker单机版
> 此模式下,对于每一份对象数据,minio直接在data下面存储这份数据,不会建立副本,也不会启用纠删码机制。因此,这种模式无论是服务实例还是磁盘都是“单点”,无任何高可用保障,磁盘损坏就表示数据丢失。
```
shell
#创建相关目录
mkdir -p /mnt/minio/data
#MinIO自定义用户名密码,注意账号密码长度有限制 账号不小于3,密码不小于8
docker run -d
\
-p 9000:9000
\
-p 9001:9001
\
--name miniotest
\
-v /mnt/minio/data:/data
\
-e "MINIO_ROOT_USER=admintest"
\
-e "MINIO_ROOT_PASSWORD=12345678"
\
quay.io/minio/minio server /data --console-address ":9001"
#访问地址http://x.x.x.x:9001/ 注意端口号要对外暴露
#创建的桶在/mnt/minio/data下
```
> 新版本将控制台和存储服务分开,对外暴露minio控制台的端口这里用的是9001端口,对象存储服务的端口是9000
2. docker单机版纠删码模式
>Minio使用纠删码 erasure code 和校验和 checksum 来保护数据免受硬件故障和无声数据损坏。 即便您丢失一半数量(N/2)的硬盘,您仍然可以恢复数据。
>
>
>
>纠删码是一种恢复丢失和损坏数据的数学算法, Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块。 这就意味着如果是12块盘,一个对象会被分成6个数据块、6个奇偶校验块,你可以丢失任意6块盘(不管其是存放的数据块还是奇偶校验块),你仍可以从剩下的盘中的数据进行恢复。
```
shell
#创建相关目录
mkdir -p /mnt/minio/{data1,data2,data3,data4,data5,data6,data7,data8}
#使用Minio Docker镜像,在8块盘中启动Minio服务:
docker run -d
\
-p 9000:9000
\
-p 9001:9001
\
--name minio
\
-v /mnt/minio/data1:/data1
\
-v /mnt/minio/data2:/data2
\
-v /mnt/minio/data3:/data3
\
-v /mnt/minio/data4:/data4
\
-v /mnt/minio/data5:/data5
\
-v /mnt/minio/data6:/data6
\
-v /mnt/minio/data7:/data7
\
-v /mnt/minio/data8:/data8
\
-e "MINIO_ROOT_USER=admintest"
\
-e "MINIO_ROOT_PASSWORD=12345678"
\
quay.io/minio/minio server /data{1...8} --console-address ":9001"
#访问地址http://x.x.x.x:9001/ 注意端口号要对外暴露
#创建的桶在/mnt/minio/{data1,...data8}下
```
3. docker集群版
- [centos7安装docker-compose](https://www.cnblogs.com/xiao987334176/p/12377113.html)
- docker compose部署https://docs.min.io/docs/deploy-minio-on-docker-compose.html
```
yaml
version: '3.7'
# Settings and configurations that are common for all containers
x-minio-common: &minio-common
image: quay.io/minio/minio:RELEASE.2022-04-01T03-41-39Z
command: server --console-address ":16001" --address ":16000" http://minio{1...4}/data{1...2}
expose:
-
"16000"
-
"16001"
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD: 12345678
healthcheck:
test:
[
"CMD", "curl", "-f", "http://localhost:16000/minio/health/live"
]
interval: 30s
timeout: 20s
retries: 3
# starts 4 docker containers running minio server instances.
# using nginx reverse proxy, load balancing, you can access
# it through port 9000.
services:
minio1:
<<:
*
minio-common
hostname: minio1
container_name: com-minio1
volumes:
-
/data/com/minio/data1-1:/data1
-
/data/com/minio/data1-2:/data2
minio2:
<<:
*
minio-common
hostname: minio2
container_name: com-minio2
volumes:
-
/data/com/minio/data2-1:/data1
-
/data/com/minio/data2-2:/data2
minio3:
<<:
*
minio-common
hostname: minio3
container_name: com-minio3
volumes:
-
/data/com/minio/data3-1:/data1
-
/data/com/minio/data3-2:/data2
minio4:
<<:
*
minio-common
hostname: minio4
container_name: com-minio4
volumes:
-
/data/com/minio/data4-1:/data1
-
/data/com/minio/data4-2:/data2
nginx:
image: nginx:1.19.2-alpine
hostname: nginx
container_name: com-minio-nginx
volumes:
-
./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
-
"16000:16000"
-
"16001:16001"
depends_on:
-
minio1
-
minio2
-
minio3
-
minio4
```
```
shell
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user
[
$time_local
]
"$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# include /etc/nginx/conf.d/
*
.conf;
upstream minio {
server minio1:16000;
server minio2:16000;
server minio3:16000;
server minio4:16000;
}
upstream console {
ip_hash;
server minio1:16001;
server minio2:16001;
server minio3:16001;
server minio4:16001;
}
server {
listen 16000;
listen
[
::
]
:16000;
server_name localhost;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# To disable buffering
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass http://minio;
}
}
server {
listen 16001;
listen
[
::
]
:16001;
server_name localhost;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# To disable buffering
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
# This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# To support websocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_pass http://console;
}
}
}
```
```
shell
docker-compose pull
docker-compose up
#如果报Failed to Setup IP tables: Unable to enable SKIP DNAT rule:
#执行 service docker restart 再执行 docker-compose up
```
4. 基本使用(springboot版,后期可以写成一个服务,对外提供feign接口)
- 引入依赖
```
java
<!-- 目前最新的版本8.3.7 -->
<dependency>
<groupId>
io.minio
</groupId>
<artifactId>
minio
</artifactId>
<version>
8.3.7
</version>
</dependency>
```
- 配置对象存储服务
```
yaml
#minio配置
minio:
url: http://X.X.X.X:9000/ #对象存储服务的URL
accessKey: minio #Access key账户
secretKey: 12345678 #Secret key密码
```
- minio配置类
```
java
@Configuration
public class MinioConfig {
@Value("${minio.url}")
private String url;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient getMinioClient() {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient;
}
}
```
- minio工具类
```
java
@Component
public class MinioUtil {
@Resource
private MinioClient minioClient;
/
**
*
创建一个桶
*
/
public void createBucket(String bucket) throws Exception {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
}
}
/
**
*
上传一个文件
*
/
public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
.stream(stream, -1, 10485760).build());
}
/
**
*
列出所有的桶
*
/
public List
<String>
listBuckets() throws Exception {
List
<Bucket>
list = minioClient.listBuckets();
List
<String>
names = new ArrayList
<>
();
list.forEach(b -> {
names.add(b.name());
});
return names;
}
/
**
*
列出一个桶中的所有文件和目录
*
/
public List
<FileInfo>
listFiles(String bucket) throws Exception {
Iterable
<Result
<
Item
>
> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucket).recursive(true).build());
List
<FileInfo>
infos = new ArrayList
<>
();
results.forEach(r->{
FileInfo info = new FileInfo();
try {
Item item = r.get();
info.setFilename(item.objectName());
info.setDirectory(item.isDir());
infos.add(info);
} catch (Exception e) {
e.printStackTrace();
}
});
return infos;
}
/
**
*
下载一个文件
*
/
public InputStream download(String bucket, String objectName) throws Exception {
InputStream stream = minioClient.getObject(
GetObjectArgs.builder().bucket(bucket).object(objectName).build());
return stream;
}
/
**
*
删除一个桶
*
/
public void deleteBucket(String bucket) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
}
/
**
*
删除一个对象
*
/
public void deleteObject(String bucket, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
}
}
```
- 具体使用
```
java
@Api(tags = "文件操作接口")
@Controller
public class FileController {
@Resource
private MinioUtil minioUtil;
@ApiOperation("上传一个文件")
@RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
@ResponseBody
public AjaxResult fileupload(@RequestParam MultipartFile uploadfile, @RequestParam String bucket,
@RequestParam(required=false) String objectName) throws Exception {
minioUtil.createBucket(bucket);
if (objectName != null) {
minioUtil.uploadFile(uploadfile.getInputStream(), bucket, objectName+"/"+uploadfile.getOriginalFilename());
} else {
minioUtil.uploadFile(uploadfile.getInputStream(), bucket, uploadfile.getOriginalFilename());
}
return AjaxResult.success();
}
@ApiOperation("列出所有的桶")
@RequestMapping(value = "/listBuckets", method = RequestMethod.GET)
@ResponseBody
public AjaxResult listBuckets() throws Exception {
return AjaxResult.success(minioUtil.listBuckets());
}
@ApiOperation("递归列出一个桶中的所有文件和目录")
@RequestMapping(value = "/listFiles", method = RequestMethod.GET)
@ResponseBody
public AjaxResult listFiles(@RequestParam String bucket) throws Exception {
return AjaxResult.success("200", minioUtil.listFiles(bucket));
}
@ApiOperation("下载一个文件")
@RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
@ResponseBody
public void downloadFile(@RequestParam String bucket, @RequestParam String objectName,
HttpServletResponse response) throws Exception {
InputStream stream = minioUtil.download(bucket, objectName);
ServletOutputStream output = response.getOutputStream();
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
IOUtils.copy(stream, output);
}
@ApiOperation("删除一个文件")
@RequestMapping(value = "/deleteFile", method = RequestMethod.GET)
@ResponseBody
public AjaxResult deleteFile(@RequestParam String bucket, @RequestParam String objectName) throws Exception {
minioUtil.deleteObject(bucket, objectName);
return AjaxResult.success();
}
@ApiOperation("删除一个桶")
@RequestMapping(value = "/deleteBucket", method = RequestMethod.GET)
@ResponseBody
public AjaxResult deleteBucket(@RequestParam String bucket) throws Exception {
minioUtil.deleteBucket(bucket);
return AjaxResult.success();
}
}
```
5. 针对分布式高可用等需要注意的点
- 各个服务的桶设置
```
每个服务可以在配置文件中定义自己的桶
```
- 集群高可用可能需要的注意事项
```
1、分布式Minio里所有的节点需要有同样的access秘钥和secret秘钥,这样这些节点才能建立联接。
2、分布式Minio使用的磁盘里必须是干净的,里面没有数据。
3、分布式Minio里的节点时间差不能超过3秒,可以使用NTP来保证时间一致。
4、在Windows下运行分布式Minio处于实验阶段,请悠着点使用。
```
-
待补充
\ No newline at end of file
pom.xml
0 → 100644
View file @
ad797d81
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
com.yifu
</groupId>
<artifactId>
springboot-minio
</artifactId>
<version>
1.0-SNAPSHOT
</version>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-thymeleaf
</artifactId>
<version>
2.1.6.RELEASE
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter
</artifactId>
<version>
2.1.6.RELEASE
</version>
<exclusions>
<!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-logging
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<version>
2.1.6.RELEASE
</version>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
<version>
2.1.6.RELEASE
</version>
<exclusions>
<!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-logging
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
<version>
2.9.2
</version>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
<version>
2.9.2
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
1.2.68
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-log4j2
</artifactId>
<version>
2.1.6.RELEASE
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<version>
3.9
</version>
</dependency>
<dependency>
<groupId>
io.minio
</groupId>
<artifactId>
minio
</artifactId>
<version>
8.3.7
</version>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-devtools
</artifactId>
<optional>
true
</optional>
<!-- 表示依赖不会传递 -->
<version>
2.1.6.RELEASE
</version>
</dependency>
</dependencies>
<build>
<finalName>
springboot-minio
</finalName>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<version>
2.1.6.RELEASE
</version>
<configuration>
<fork>
true
</fork>
<!-- 如果没有该配置,devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- 指定maven编译方式为jdk1.8版本 -->
<profiles>
<profile>
<id>
jdk-1.8
</id>
<activation>
<activeByDefault>
true
</activeByDefault>
<jdk>
1.8
</jdk>
</activation>
<properties>
<maven.compiler.source>
1.8
</maven.compiler.source>
<maven.compiler.target>
1.8
</maven.compiler.target>
<maven.compiler.compilerVersion>
1.8
</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
</project>
\ No newline at end of file
src/main/java/com/yifu/minio/Application.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
/**
* @author licancan
* @description 启动类
* @date 2022-04-07 16:03:05
*/
@SpringBootApplication
public
class
Application
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
Application
.
class
,
args
);
}
}
src/main/java/com/yifu/minio/Swagger2.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
springfox.documentation.builders.ApiInfoBuilder
;
import
springfox.documentation.builders.PathSelectors
;
import
springfox.documentation.builders.RequestHandlerSelectors
;
import
springfox.documentation.service.ApiInfo
;
import
springfox.documentation.spi.DocumentationType
;
import
springfox.documentation.spring.web.plugins.Docket
;
import
springfox.documentation.swagger2.annotations.EnableSwagger2
;
/**
* @author licancan
* @description Swagger2配置
* @date 2022-04-07 16:09:02
*/
@Configuration
@EnableSwagger2
public
class
Swagger2
{
@Bean
public
Docket
createRestApi
()
{
return
new
Docket
(
DocumentationType
.
SWAGGER_2
)
.
apiInfo
(
apiInfo
())
.
select
()
.
apis
(
RequestHandlerSelectors
.
basePackage
(
"com.yifu.minio.controller"
))
.
paths
(
PathSelectors
.
any
())
.
build
();
}
private
ApiInfo
apiInfo
()
{
return
new
ApiInfoBuilder
()
.
title
(
"springboot利用swagger构建api文档"
)
.
description
(
"简单优雅的restful风格"
)
.
termsOfServiceUrl
(
"https://gitee.com/canexplorer"
)
.
version
(
"1.0"
)
.
build
();
}
}
src/main/java/com/yifu/minio/config/CorsConfig.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.servlet.config.annotation.CorsRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
/**
* @author licancan
* @description 跨域配置
* @date 2022-04-07 16:05:31
*/
@Configuration
public
class
CorsConfig
{
@Bean
public
WebMvcConfigurer
corsConfigurer
()
{
return
new
WebMvcConfigurer
()
{
@Override
//重写父类提供的跨域请求处理的接口
public
void
addCorsMappings
(
CorsRegistry
registry
)
{
//添加映射路径
registry
.
addMapping
(
"/**"
)
//放行哪些原始域
.
allowedOrigins
(
"*"
)
//是否发送Cookie信息
.
allowCredentials
(
true
)
//放行哪些原始域(请求方式)
.
allowedMethods
(
"GET"
,
"POST"
,
"PUT"
,
"DELETE"
)
//放行哪些原始域(头部信息)
.
allowedHeaders
(
"*"
)
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.
exposedHeaders
(
"token"
);
}
};
}
}
src/main/java/com/yifu/minio/config/MinioConfig.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
config
;
import
io.minio.MinioClient
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* @author licancan
* @description minio配置
* @date 2022-04-07 16:06:44
*/
@Configuration
public
class
MinioConfig
{
@Value
(
"${minio.url}"
)
private
String
url
;
@Value
(
"${minio.accessKey}"
)
private
String
accessKey
;
@Value
(
"${minio.secretKey}"
)
private
String
secretKey
;
@Bean
public
MinioClient
getMinioClient
()
{
MinioClient
minioClient
=
MinioClient
.
builder
().
endpoint
(
url
)
.
credentials
(
accessKey
,
secretKey
).
build
();
return
minioClient
;
}
}
src/main/java/com/yifu/minio/controller/FileController.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
controller
;
import
com.yifu.minio.domain.AjaxResult
;
import
com.yifu.minio.util.MinioUtil
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.tomcat.util.http.fileupload.IOUtils
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.InputStream
;
import
java.net.URLEncoder
;
/**
* @author licancan
* @description TODO
* @date 2022-04-07 16:24:06
*/
@Api
(
tags
=
"文件操作接口"
)
@Controller
public
class
FileController
{
@Resource
private
MinioUtil
minioUtil
;
@ApiOperation
(
"上传一个文件"
)
@RequestMapping
(
value
=
"/uploadfile"
,
method
=
RequestMethod
.
POST
)
@ResponseBody
public
AjaxResult
fileupload
(
@RequestParam
MultipartFile
uploadfile
,
@RequestParam
String
bucket
,
@RequestParam
(
required
=
false
)
String
objectName
)
throws
Exception
{
minioUtil
.
createBucket
(
bucket
);
if
(
objectName
!=
null
)
{
minioUtil
.
uploadFile
(
uploadfile
.
getInputStream
(),
bucket
,
objectName
+
"/"
+
uploadfile
.
getOriginalFilename
());
}
else
{
minioUtil
.
uploadFile
(
uploadfile
.
getInputStream
(),
bucket
,
uploadfile
.
getOriginalFilename
());
}
return
AjaxResult
.
success
();
}
@ApiOperation
(
"列出所有的桶"
)
@RequestMapping
(
value
=
"/listBuckets"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
AjaxResult
listBuckets
()
throws
Exception
{
return
AjaxResult
.
success
(
minioUtil
.
listBuckets
());
}
@ApiOperation
(
"递归列出一个桶中的所有文件和目录"
)
@RequestMapping
(
value
=
"/listFiles"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
AjaxResult
listFiles
(
@RequestParam
String
bucket
)
throws
Exception
{
return
AjaxResult
.
success
(
"200"
,
minioUtil
.
listFiles
(
bucket
));
}
@ApiOperation
(
"下载一个文件"
)
@RequestMapping
(
value
=
"/downloadFile"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
void
downloadFile
(
@RequestParam
String
bucket
,
@RequestParam
String
objectName
,
HttpServletResponse
response
)
throws
Exception
{
InputStream
stream
=
minioUtil
.
download
(
bucket
,
objectName
);
ServletOutputStream
output
=
response
.
getOutputStream
();
response
.
setHeader
(
"Content-Disposition"
,
"attachment;filename="
+
URLEncoder
.
encode
(
objectName
.
substring
(
objectName
.
lastIndexOf
(
"/"
)
+
1
),
"UTF-8"
));
response
.
setContentType
(
"application/octet-stream"
);
response
.
setCharacterEncoding
(
"UTF-8"
);
IOUtils
.
copy
(
stream
,
output
);
}
@ApiOperation
(
"删除一个文件"
)
@RequestMapping
(
value
=
"/deleteFile"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
AjaxResult
deleteFile
(
@RequestParam
String
bucket
,
@RequestParam
String
objectName
)
throws
Exception
{
minioUtil
.
deleteObject
(
bucket
,
objectName
);
return
AjaxResult
.
success
();
}
@ApiOperation
(
"删除一个桶"
)
@RequestMapping
(
value
=
"/deleteBucket"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
AjaxResult
deleteBucket
(
@RequestParam
String
bucket
)
throws
Exception
{
minioUtil
.
deleteBucket
(
bucket
);
return
AjaxResult
.
success
();
}
}
src/main/java/com/yifu/minio/domain/AjaxResult.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
domain
;
import
java.util.HashMap
;
/**
* @author licancan
* @description 响应结果类
* @date 2022-04-07 16:15:35
*/
public
class
AjaxResult
extends
HashMap
<
String
,
Object
>
{
private
static
final
long
serialVersionUID
=
1L
;
/** 状态码 */
public
static
final
String
CODE_TAG
=
"code"
;
/** 返回内容 */
public
static
final
String
MSG_TAG
=
"msg"
;
/** 数据对象 */
public
static
final
String
DATA_TAG
=
"data"
;
/**
* 状态类型
*/
public
enum
Type
{
/** 成功 */
SUCCESS
(
0
),
/** 警告 */
WARN
(
301
),
/** 错误 */
ERROR
(
500
);
private
final
int
value
;
Type
(
int
value
)
{
this
.
value
=
value
;
}
public
int
value
()
{
return
this
.
value
;
}
}
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public
AjaxResult
()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param type 状态类型
* @param msg 返回内容
*/
public
AjaxResult
(
Type
type
,
String
msg
)
{
super
.
put
(
CODE_TAG
,
type
.
value
);
super
.
put
(
MSG_TAG
,
msg
);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param type 状态类型
* @param msg 返回内容
* @param data 数据对象
*/
public
AjaxResult
(
Type
type
,
String
msg
,
Object
data
)
{
super
.
put
(
CODE_TAG
,
type
.
value
);
super
.
put
(
MSG_TAG
,
msg
);
if
(
data
!=
null
)
{
super
.
put
(
DATA_TAG
,
data
);
}
}
/**
* 方便链式调用
*
* @param key 键
* @param value 值
* @return 数据对象
*/
@Override
public
AjaxResult
put
(
String
key
,
Object
value
)
{
super
.
put
(
key
,
value
);
return
this
;
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public
static
AjaxResult
success
()
{
return
AjaxResult
.
success
(
"操作成功"
);
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public
static
AjaxResult
success
(
Object
data
)
{
return
AjaxResult
.
success
(
"操作成功"
,
data
);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public
static
AjaxResult
success
(
String
msg
)
{
return
AjaxResult
.
success
(
msg
,
null
);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public
static
AjaxResult
success
(
String
msg
,
Object
data
)
{
return
new
AjaxResult
(
Type
.
SUCCESS
,
msg
,
data
);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @return 警告消息
*/
public
static
AjaxResult
warn
(
String
msg
)
{
return
AjaxResult
.
warn
(
msg
,
null
);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public
static
AjaxResult
warn
(
String
msg
,
Object
data
)
{
return
new
AjaxResult
(
Type
.
WARN
,
msg
,
data
);
}
/**
* 返回错误消息
*
* @return
*/
public
static
AjaxResult
error
()
{
return
AjaxResult
.
error
(
"操作失败"
);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public
static
AjaxResult
error
(
String
msg
)
{
return
AjaxResult
.
error
(
msg
,
null
);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public
static
AjaxResult
error
(
String
msg
,
Object
data
)
{
return
new
AjaxResult
(
Type
.
ERROR
,
msg
,
data
);
}
}
src/main/java/com/yifu/minio/domain/FileInfo.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
domain
;
/**
* @author licancan
* @description 文件类
* @date 2022-04-07 16:13:47
*/
public
class
FileInfo
{
String
filename
;
Boolean
directory
;
public
String
getFilename
()
{
return
filename
;
}
public
void
setFilename
(
String
filename
)
{
this
.
filename
=
filename
;
}
public
Boolean
getDirectory
()
{
return
directory
;
}
public
void
setDirectory
(
Boolean
directory
)
{
this
.
directory
=
directory
;
}
}
src/main/java/com/yifu/minio/util/MinioUtil.java
0 → 100644
View file @
ad797d81
package
com
.
yifu
.
minio
.
util
;
import
com.yifu.minio.domain.FileInfo
;
import
io.minio.*
;
import
io.minio.messages.Bucket
;
import
io.minio.messages.Item
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author licancan
* @description minio工具类
* @date 2022-04-07 16:11:11
*/
@Component
public
class
MinioUtil
{
@Resource
private
MinioClient
minioClient
;
/**
* 创建一个桶
*/
public
void
createBucket
(
String
bucket
)
throws
Exception
{
boolean
found
=
minioClient
.
bucketExists
(
BucketExistsArgs
.
builder
().
bucket
(
bucket
).
build
());
if
(!
found
)
{
minioClient
.
makeBucket
(
MakeBucketArgs
.
builder
().
bucket
(
bucket
).
build
());
}
}
/**
* 上传一个文件
*/
public
void
uploadFile
(
InputStream
stream
,
String
bucket
,
String
objectName
)
throws
Exception
{
minioClient
.
putObject
(
PutObjectArgs
.
builder
().
bucket
(
bucket
).
object
(
objectName
)
.
stream
(
stream
,
-
1
,
10485760
).
build
());
}
/**
* 列出所有的桶
*/
public
List
<
String
>
listBuckets
()
throws
Exception
{
List
<
Bucket
>
list
=
minioClient
.
listBuckets
();
List
<
String
>
names
=
new
ArrayList
<>();
list
.
forEach
(
b
->
{
names
.
add
(
b
.
name
());
});
return
names
;
}
/**
* 列出一个桶中的所有文件和目录
*/
public
List
<
FileInfo
>
listFiles
(
String
bucket
)
throws
Exception
{
Iterable
<
Result
<
Item
>>
results
=
minioClient
.
listObjects
(
ListObjectsArgs
.
builder
().
bucket
(
bucket
).
recursive
(
true
).
build
());
List
<
FileInfo
>
infos
=
new
ArrayList
<>();
results
.
forEach
(
r
->{
FileInfo
info
=
new
FileInfo
();
try
{
Item
item
=
r
.
get
();
info
.
setFilename
(
item
.
objectName
());
info
.
setDirectory
(
item
.
isDir
());
infos
.
add
(
info
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
});
return
infos
;
}
/**
* 下载一个文件
*/
public
InputStream
download
(
String
bucket
,
String
objectName
)
throws
Exception
{
InputStream
stream
=
minioClient
.
getObject
(
GetObjectArgs
.
builder
().
bucket
(
bucket
).
object
(
objectName
).
build
());
return
stream
;
}
/**
* 删除一个桶
*/
public
void
deleteBucket
(
String
bucket
)
throws
Exception
{
minioClient
.
removeBucket
(
RemoveBucketArgs
.
builder
().
bucket
(
bucket
).
build
());
}
/**
* 删除一个对象
*/
public
void
deleteObject
(
String
bucket
,
String
objectName
)
throws
Exception
{
minioClient
.
removeObject
(
RemoveObjectArgs
.
builder
().
bucket
(
bucket
).
object
(
objectName
).
build
());
}
}
src/main/resources/application.yml
0 → 100644
View file @
ad797d81
server
:
port
:
8080
logging
:
config
:
classpath:log4j2.xml
spring
:
servlet
:
multipart
:
max-file-size
:
100MB
max-request-size
:
1000MB
#minio配置
minio
:
url
:
http://192.168.1.65:16000/
#对象存储服务的URL
accessKey
:
minio
#Access key账户
secretKey
:
12345678
#Secret key密码
\ No newline at end of file
src/main/resources/log4j2.xml
0 → 100644
View file @
ad797d81
<?xml version="1.0" encoding="UTF-8"?>
<configuration
status=
"off"
>
<Properties>
<!-- 日志存储路径 -->
<Property
name=
"baseDir"
>
./logs
</Property>
</Properties>
<CustomLevels>
<CustomLevel
name=
"AUDIT"
intLevel=
"50"
/>
</CustomLevels>
<Appenders>
<Console
name=
"console"
target=
"SYSTEM_OUT"
>
<PatternLayout
charset=
"UTF-8"
pattern=
"[%-5p] [%d{HH:mm:ss}] %c - %m%n"
/>
</Console>
<!-- 自定义 -->
<RollingFile
name=
"RollingFileAUDIT"
fileName=
"${baseDir}/logservice-web/audit-log/audit-log.log"
filePattern=
"${baseDir}/logservice-web/audit-log/audit-log-%i.log"
>
<ThresholdFilter
level=
"AUDIT"
onMatch=
"ACCEPT"
onMismatch=
"DENY"
/>
<PatternLayout
pattern=
"[%d{yyyy/MM/dd HH:mm:ssS}][%p][LOGSERVICE][日志系统]%m%n"
/>
<Policies>
<SizeBasedTriggeringPolicy
size=
"10 MB"
/>
</Policies>
<!-- 保存最大文件个数 -->
<DefaultRolloverStrategy
max=
"50"
/>
</RollingFile>
<!--Trace级别日志输出-->
<RollingFile
name=
"system-trace"
fileName=
"${baseDir}/logservice-web/trace.log"
filePattern=
"${baseDir}/logservice-web/trace-%i.log"
>
<Filters>
<ThresholdFilter
level=
"debug"
onMatch=
"DENY"
onMismatch=
"NEUTRAL"
/>
<ThresholdFilter
level=
"trace"
onMatch=
"ACCEPT"
onMismatch=
"DENY"
/>
</Filters>
<PatternLayout
charset=
"UTF-8"
pattern=
"[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n"
/>
<Policies>
<!-- 日志文件大小 -->
<SizeBasedTriggeringPolicy
size=
"10 MB"
/>
</Policies>
<!-- 保存最大文件个数 -->
<DefaultRolloverStrategy
max=
"50"
/>
</RollingFile>
<!--Info级别日志输出-->
<RollingFile
name=
"system-info"
fileName=
"${baseDir}/logservice-web/info.log"
filePattern=
"${baseDir}/logservice-web/info-%i.log"
>
<Filters>
<ThresholdFilter
level=
"warn"
onMatch=
"DENY"
onMismatch=
"NEUTRAL"
/>
<ThresholdFilter
level=
"info"
onMatch=
"ACCEPT"
onMismatch=
"DENY"
/>
</Filters>
<PatternLayout
charset=
"UTF-8"
pattern=
"[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n"
/>
<Policies>
<SizeBasedTriggeringPolicy
size=
"10 MB"
/>
</Policies>
<DefaultRolloverStrategy
max=
"50"
/>
</RollingFile>
<!--Debug级别日志输出-->
<RollingFile
name=
"system-debug"
fileName=
"${baseDir}/logservice-web/debug.log"
filePattern=
"${baseDir}/logservice-web/debug-%i.log"
>
<Filters>
<ThresholdFilter
level=
"info"
onMatch=
"DENY"
onMismatch=
"NEUTRAL"
/>
<ThresholdFilter
level=
"debug"
onMatch=
"ACCEPT"
onMismatch=
"DENY"
/>
</Filters>
<PatternLayout
charset=
"UTF-8"
pattern=
"[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n"
/>
<Policies>
<SizeBasedTriggeringPolicy
size=
"10 MB"
/>
</Policies>
<DefaultRolloverStrategy
max=
"50"
/>
</RollingFile>
<!--Error级别日志输出-->
<RollingFile
name=
"system-error"
fileName=
"${baseDir}/logservice-web/error.log"
filePattern=
"${baseDir}/logservice-web/error-%i.log"
>
<Filters>
<ThresholdFilter
level=
"AUDIT"
onMatch=
"DENY"
onMismatch=
"NEUTRAL"
/>
<ThresholdFilter
level=
"error"
onMatch=
"ACCEPT"
onMismatch=
"DENY"
/>
</Filters>
<PatternLayout
charset=
"UTF-8"
pattern=
"[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n"
/>
<Policies>
<SizeBasedTriggeringPolicy
size=
"10 MB"
/>
</Policies>
<DefaultRolloverStrategy
max=
"50"
/>
</RollingFile>
</Appenders>
<Loggers>
<logger
name=
"io.netty"
level=
"INFO"
></logger>
<logger
name=
"org.springframework"
level=
"INFO"
></logger>
<logger
name=
"org.elasticsearch"
level=
"INFO"
></logger>
<root
level=
"INFO"
>
<appender-ref
ref=
"console"
/>
<appender-ref
ref=
"system-info"
/>
<appender-ref
ref=
"system-trace"
/>
<appender-ref
ref=
"system-debug"
/>
<appender-ref
ref=
"system-error"
/>
<appender-ref
ref=
"RollingFileAUDIT"
/>
</root>
</Loggers>
</configuration>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment