Commit ad797d81 authored by licancan's avatar licancan

minio测试demo

parents
# springboot-minio
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。 本项目集成Minio的java客户端SDK,对Minio文件服务器进行读写,将操作封装为MinioUtil工具,直接在项目中可以复用。其操作主要包括:
- 上传文件
- 下载文件
- 读取桶列表
- 读取桶中的文件列表
- 删除桶
- 删除文件
\ No newline at end of file
# 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
<?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
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);
}
}
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();
}
}
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");
}
};
}
}
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;
}
}
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();
}
}
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);
}
}
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;
}
}
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());
}
}
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
<?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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment