minio安装部署minio、nginx代理、minio封装工具类

1,790 阅读13分钟

[TOC]

minio安装部署minio、nginx代理、minio封装工具类

官网:docs.minio.org.cn/docs

imgMinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。 MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

一、单机版

1.1 创建目录

mkdir -p /opt/minio/bin
mkdir -p /opt/minio/data

1.2 下载minio:下载地址:www.minio.org.cn/download.sh…

cd /opt/minio/bin
wget http://dl.minio.org.cn/server/minio/release/linux-amd64/minio
chmod +x minio

1.3 创建minion的执行脚本文件:

vi /opt/minio/bin/run.sh 添加如下内容:

#!/bin/bash
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=Flask_324

/opt/minio/bin/minio server /opt/minio/data --address ":9000" --console-address ":9001"

1.4 设置minio开机自启服务

vi /etc/systemd/system/minio.service 添加如下内容:

[Unit]
Description=Minio service
Documentation=https://docs.minio.io/
 
[Service]
WorkingDirectory=/opt/minio/
ExecStart=/opt/minio/bin/run.sh
 
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target

1.5 启动MinIO

systemctl enable minio.service #将上一步创建的minio.service文件添加到开机启动项中
systemctl start minio.service #启动minio
systemctl status minio.service #查看minio状态

systemctl stop minio.service #停止minio

1.6 开放9000、9001端口

firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=9001/tcp --permanent

systemctl restart firewalld.service

1.7 打开浏览器访问: http://ip:9000

二、集群版

2.1 安装CentOS7.x自定义分区方法

步骤1:在安装系统的界面中,选择“INSTALLATION DESTINATION”,进入到系统的分区界面

img

步骤2:选择下方选项框“i will configure partitioning”,选择完成后点击“Done”

img

步骤3:选择如何分区硬盘的方式“Standard Partition”,并点击下方“+”符号创建自定义磁盘空间

img

步骤4:第一步:创建/boot空间,大小设置为200,单位默认为MB,在实际的工作中可针对服务器的作 用和性能调节此值的大小

img

步骤5:第二步:创建swap的使用量,大小设置为2048,单位默认为MB,在实际的工作中可针对服务器的作用和性能调节此值的大小

img

步骤6:第三步:创建biosboot空间,大小设置为1MB,此空间如果不创建在一些环境中系统将会出错

img

步骤7:最后一步:创建/空间,大小设置为空,将划分余下的所有空间给/分区,在实际的工作中可针对服务器的作用和性能调节此值的大小

img

步骤8:设置完成后可检查最后的设置情况,最后点击“Done”进入安装系统的下一步

刚安装好的虚拟机可能没有ifconfig和vim命令,如果没有执行下面命令

yum search ifconfig
yum -y install vim*

查看虚拟机IP地址命令:ifconfig 或者 ip add

2.2 minio分布式集群的详细搭建

(先把一个服务器配置好,然后克隆三个)

2.2.1 基础环境

2.2.1.1 操作系统:CentOS 7.3 2.2.1.2 Minio下载

将下载的minio移动到 /opt/minio/文件夹下

或者直接下载:wget dl.minio.io/server/mini…

2.2.1.3 机器资源(根据实际情况更改IP地址)

192.168.129.133  挂载磁盘路径:/data/minio_data
192.168.129.135 挂载磁盘路径:/data/minio_data
192.168.129.136 挂载磁盘路径:/data/minio_data
192.168.129.137 挂载磁盘路径:/data/minio_data

生产环境强烈建议至少四台机器,这也是官方的建议要求,这样的话就可以做到挂掉一台机器集群 依然可以读写,挂掉两台机器集群依然可读,本文仅以四台机器为例子说明如何搭建集群

2.2.2 准备工作

——(从这里开始实际操作)

2.2.2.1 创建相关目录(所有节点,上面四台机器都创建相同路径的文件夹)

[root@localhost /]# mkdir /data/minio_data/

2.2.2.2 需要将新建的目录挂在到对应的磁盘下,磁盘不挂载好,集群启动会报错:找不到磁盘,如下:

根据实际情况挂载sda+数字(例如:sda1)

[root@localhost /]# df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 475M     0  475M   0% /dev
tmpfs                    487M     0  487M   0% /dev/shm
tmpfs                    487M  7.7M  479M   2% /run
tmpfs                    487M     0  487M   0% /sys/fs/cgroup
/dev/mapper/centos-root   17G  7.4G  9.6G  44% /
/dev/sda1               1014M  137M  878M  14% /boot
tmpfs                     98M     0   98M   0% /run/user/0
[root@localhost /]# mount /dev/sda1 /data/minio_data/
mount: /dev/sda1 is already mounted or /data/minio_data busy
       /dev/sda1 is already mounted on /boot
       /dev/sda1 is already mounted on /data/minio_data
[root@localhost /]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   20G  0 disk 
├─sda1            8:1    0    1G  0 part /data/minio_data
└─sda2            8:2    0   19G  0 part 
  ├─centos-root 253:0    0   17G  0 lvm  /
  └─centos-swap 253:1    0    2G  0 lvm  [SWAP]
sr0              11:0    1  4.4G  0 rom  
[root@localhost /]#

2.2.2.3 创建启动脚本目录

[root@localhost /]# mkdir /opt/minio/

2.2.3 编写集群启动脚本(所有节点配置文件相同)

2.2.3.1 脚本如下:

[root@localhost /]# vim /opt/minio/run.sh 
 
#!/bin/bash
export MINIO_ACCESS_KEY=Xxyminio
export MINIO_SECRET_KEY=Test123456
 
/opt/minio/minio server \
http://192.168.129.133/data/minio_data/data1 http://192.168.129.135/data/minio_data/data1 \
http://192.168.129.136/data/minio_data/data1 http://192.168.129.137/data/minio_data/data1

其中,“MINIO_ACCESS_KEY”为用户名,“MINIO_SECRET_KEY”为密码,密码不能设置过于简单,不然minio会启动失败

2.2.3.2 创建好的/opt/minio/目录下的结构如下图:

img

2.2.4 编写服务脚本(所有节点)

[root@localhost minio]# vim /usr/lib/systemd/system/minio.service 
 
[Unit]
Description=Minio service
Documentation=https://docs.minio.io/
 
[Service]
WorkingDirectory=/opt/minio/
ExecStart=/opt/minio/run.sh
 
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target

其中,“WorkingDirectory”为启动脚本目录,“ExecStart”为指定集群启动脚本

2.2.5 克隆复制三个服务器,记得打开端口或者直接关闭防火墙,修改服务器IP地址

	firewall-cmd --zone=public --add-port=9000/tcp --permanent
	firewall-cmd --reload
修改IP地址:方法一:
查看IP地址:ip add  或者  ifconfig
修改IP地址:nmtui ——直接调出修改窗口
重启网络服务:systemctl restart network
如想进一步了解请访问:https://jingyan.baidu.com/article/e4d08ffd63ea390fd2f60d34.html

修改IP地址:方法二:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
(1)bootproto=static
(2)onboot=yes
(3)在最后加上几行,IP地址、子网掩码、网关、dns服务器
	IPADDR=192.168.1.160
	NETMASK=255.255.255.0
	GATEWAY=192.168.1.1
	DNS1=119.29.29.29
	DNS2=8.8.8.8
最后重启网络服务:systemctl restart network
进一步了解请访问:https://blog.csdn.net/pengyuan751/article/details/96978161

2.2.6 启动测试

2.2.6.1 将下载好的minio文件赋予权限

[root@localhost minio]# chmod +x /opt/minio/minio

2.2.6.2 赋予启动脚本文件权限

[root@localhost minio]# chmod +x /opt/minio/run.sh

2.2.6.3 依次启动每个服务器的minio

[root@localhost minio]# systemctl daemon-reload
[root@localhost minio]# 
[root@localhost minio]# systemctl start minio
[root@localhost minio]# 
[root@localhost minio]# systemctl status minio
● minio.service - Minio service
   Loaded: loaded (/usr/lib/systemd/system/minio.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2020-04-22 10:32:54 CST; 44s ago
     Docs: https://docs.minio.io/
 Main PID: 1569 (run.sh)
   CGroup: /system.slice/minio.service
           ├─1569 /bin/bash /opt/minio/run.sh
           └─1570 /opt/minio/minio server http://192.168.129.133/data/minio_data/data1 http://192.168.129.135/data/minio_data/data1 http://192....
 
Apr 22 10:32:54 localhost.localdomain systemd[1]: Started Minio service.
Apr 22 10:33:17 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 18s)
Apr 22 10:33:20 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 21s)
Apr 22 10:33:23 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 24s)
Apr 22 10:33:26 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 27s)
Apr 22 10:33:29 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 30s)
Apr 22 10:33:32 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 33s)
Apr 22 10:33:35 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 36s)
Apr 22 10:33:38 localhost.localdomain run.sh[1569]: Waiting for a minimum of 2 disks to come online (elapsed 39s)
[root@localhost minio]# 

2.2.6.4 测试

浏览器输入集群任意节点地址+9000端口,即可访问minio,用户名密码为前面设置的“MINIO_ACCESS_KEY”和“MINIO_SECRET_KEY”,可创建“bucket”并上传文件测试

img

2.2.7 配置负载均衡 (nginx反向代理)

2.2.7.1、nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

        upstream minio-server
        {
			#weight为服务器权重,与访问频率成正比,
			#max_fails最大超时次数,fail_timeout服务器代理监听超时时间
                server 192.168.92.136:9000 weight=25 max_fails=2 fail_timeout=30s;
                server 192.168.92.137:9000 weight=25 max_fails=2 fail_timeout=30s;
                server 192.168.92.138:9000 weight=25 max_fails=2 fail_timeout=30s;
                server 192.168.92.139:9000 weight=25 max_fails=2 fail_timeout=30s;
        }
    server {
        listen 80;
        server_name localhost;
        charset utf-8;
        default_type text/html;

        #server_name  itrip.project.bdqn.cn;  #配置域名,还要配置win下面的hosts文件
        # root /data/itrip/itripfront;      #前端工厂
        #index index.html;  #默认页

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location /{
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-For $remote_addr;
                client_body_buffer_size 10M;
                client_max_body_size 10G;
                proxy_buffers 1024 4k;
                proxy_read_timeout 3000;
			#实现故障转移
                proxy_next_upstream error timeout http_404;
                proxy_pass http://minio-server;
        }

        #配置日志文件
        access_log /data/logs/nginx/app_access.log;

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

2.2.7.2 打开nginx 80端口和重启

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
检测配置文件是否有错误:/usr/sbin/nginx -t
重启:/usr/sbin/nginx -s reload

2.3.Docker集群安装部署minio

2.3.1 Docker安装

略 。。。

2.3.2 Docker-Compose安装

	docker-compose是 docker 容器的一种单机编排服务,docker-compose 是一个管理多个容器的工具,比如可以解决容器之间的依赖关系,当在宿主机启动较多的容器时候,如果都是手动操作会觉得比较麻烦而且容易出错,这个时候推荐使用 docker的单机编排工具 docker-compose
	
安装之前说明:以下是使用离线安装

2.3.2.1 下载 Docker-Compose

访问https://github.com/docker/compose/releases,下载 docker-compose-Linux-x86_64,我是复制链接地址,在迅雷中下载的,下载后,将docker-compose-Linux-x86_64重命名为docker-compose

2.3.2.2 使用Xftp,将刚才下载的docker-compose文件上传到centos7的/usr/local/bin/目录下

2.3.2.3 执行命令

将文件改名为docker-compose
[root@localhost ~]# mv /usr/local/bin/docker-compose-Linux-x86_64.64 /usr/local/bin/docker-compose
给文件添加可执行权限:
[root@localhost~]# chmod +x /usr/local/bin/docker-compose
# 查看docker-compose版本
[root@localhost~]# docker-compose -v

2.3.3 编写docker-compose.yml文件

#docker-compose.yaml
version: '3'

# starts 4 docker containers running minio server instances. Each
# minio server's web interface will be accessible on the host at port
# 9001 through 9004.
services:
  minio1:
    image: minio/minio:RELEASE.2020-08-08T04-50-06Z
    container_name: minio_1
    restart: always
    volumes:
      - data1-1:/data1
      - data1-2:/data2
    ports:
      - "9001:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio2:
    image: minio/minio:RELEASE.2020-08-08T04-50-06Z
    container_name: minio_2
    restart: always
    volumes:
      - data2-1:/data1
      - data2-2:/data2
    ports:
      - "9002:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio3:
    image: minio/minio:RELEASE.2020-08-08T04-50-06Z
    container_name: minio_3
    restart: always
    volumes:
      - data3-1:/data1
      - data3-2:/data2
    ports:
      - "9003:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio4:
    image: minio/minio:RELEASE.2020-08-08T04-50-06Z
    container_name: minio_4
    restart: always
    volumes:
      - data4-1:/data1
      - data4-2:/data2
    ports:
      - "9004:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
  #nginx配置       
  nginx:
    image: nginx:latest
    container_name: minio_nginx
    restart: always
    hostname: nginx
    volumes:
      - /usr/local/install/conf/nginx:/etc/nginx
    ports:  #端口映射
      - "80:80"
    depends_on: #依赖那些容器
      - minio1
      - minio2
      - minio3
      - minio4

## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
  data1-1:
  data1-2:
  data2-1:
  data2-2:
  data3-1:
  data3-2:
  data4-1:
  data4-2:

networks:
    default:                    
        external:               #加入外部网络
            name: dockernetwork

2.3.4上传yml文件,并运行,具体步骤如下:

#1.Linux创建存放docker-compose.yml文件路径
mkdir /usr/local/install/minio
#2.把docker-compose.yml文件上传到新建的 /usr/local/install/minio
#3.compose以守护进程模式运行加-d选项
docker-compose up -d

2.3.5打开对应的端口(或者关闭防火墙,这个方法不推荐)

例如:

firewall-cmd --zone=public --add-port=9001/tcp --permanent
firewall-cmd --zone=public --add-port=9002/tcp --permanent
firewall-cmd --zone=public --add-port=9003/tcp --permanent
firewall-cmd --zone=public --add-port=9004/tcp --permanent
firewall-cmd --reload

2.3.6minio测试

直接在浏览器中输入对应的IP地址:http://IP:9001 或者 http://IP:9002http://IP:9003http://IP:9004

2.3.7 配置负载均衡(nginx反向代理)

nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


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;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    #配置访问minio的负载均衡
    upstream minio_server{
       server 192.168.1.114:9001;
       server 192.168.1.114:9002;
       server 192.168.1.114:9003;
       server 192.168.1.114:9004;
    }

    include /etc/nginx/conf.d/*.conf;
}

default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    #location / {
    #    root   /usr/share/nginx/html;
    #    index  index.html index.htm;
    #}

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $remote_addr;
        client_body_buffer_size 10M;
        client_max_body_size 10G;
        proxy_buffers 1024 4k;
        proxy_read_timeout 300;
        proxy_next_upstream error timeout http_404;
        proxy_pass http://minio_server;
        #实现故障转移
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;

    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

2.3.8 打开nginx 80 端口

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload

2.3.9 测试

直接输入对应的IP地址:http://IP 出现以下界面成功

img


三、使用Java操作

3.1 设置服务器时间

方法1
    1. 手动修改系统时间
       date -s 20210127
       date -s 16:01:32
       date -s "20210127 16:01:32"
    2. 将系统时间写入硬件时间
       hwclock --systohc
方法2
    1. 安装ntp ntpdate
       yum -y install ntp ntpdate
    2. 与时间服务器同步时间
       ntpdate cn.pool.ntp.org
    3. 将系统时间写入硬件时间
       hwclock --systohc

如果不做以上设置在上传文件的时候可能会报错误:

抛出异常:The difference between the request time and the server’s time is too large

3.2 minio工具类封装——MinioAPI

package com.example.minio.upload.util;

import io.minio.*;
import io.minio.http.Method;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.InputStream;

@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioAPI {
    /**
     * minio参数
     */
    private String ENDPOINT;
    private String ACCESS_KEY;
    private String SECRET_KEY;

   /* private static final String ENDPOINT = "http://192.168.92.133:9000";
    private static final String ACCESS_KEY = "minioadmin";
    private static final String SECRET_KEY = "minioadmin";*/
   /**
   * 桶占位符
   */
  private static final String BUCKET_PARAM = "${bucket}";
  /**
   * bucket权限-只读
   */
  private static final String READ_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
  /**
   * bucket权限-只写
   */
  private static final String WRITE_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
  /**
   * bucket权限-读写
   */
  private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
 
  /**
   * 文件url前半段
   *
   * @param bucket 桶
   * @return 前半段
   */
  public String getObjectPrefixUrl(String bucket) {
      return String.format("%s/%s/", ENDPOINT, bucket);
  }
 
  /**
   * 创建桶
   *
   * @param bucket 桶
   */
  public void makeBucket(String bucket) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      // 判断桶是否存在
      boolean isExist = client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
      if (!isExist) {
          // 新建桶
          client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
      }
  }
 
  /**
   * 更新桶权限策略
   *
   * @param bucket 桶
   * @param policy 权限
   */
  public void setBucketPolicy(String bucket, String policy) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      switch (policy) {
          case "read-only":
              client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
              break;
          case "write-only":
              client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
              break;
          case "read-write":
              client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
              break;
          case "none":
          default:
              break;
      }
  }
 
  /**
   * 上传本地文件
   *
   * @param bucket    桶
   * @param objectKey 文件key
   * @param filePath  文件路径
   * @return 文件url
   */
  public String uploadFile(String bucket, String objectKey, String filePath) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      client.uploadObject(UploadObjectArgs.builder().bucket(bucket).object(objectKey).filename(filePath).contentType("image/png").build());
      return getObjectPrefixUrl(bucket) + objectKey;
  }
 
  /**
   * 流式上传文件
   *
   * @param bucket      桶
   * @param objectKey   文件key
   * @param inputStream 文件输入流
   * @return 文件url
   */
  public String uploadInputStream(String bucket, String objectKey, InputStream inputStream) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      client.putObject(PutObjectArgs.builder().bucket(bucket).object(objectKey).stream(inputStream, inputStream.available(), -1).contentType("image/png").build());
      return getObjectPrefixUrl(bucket) + objectKey;
  }
 
  /**
   * 下载文件
   *
   * @param bucket    桶
   * @param objectKey 文件key
   * @return 文件流
   */
  public InputStream download(String bucket, String objectKey) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      return client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
  }
 
  /**
   * 文件复制
   *
   * @param sourceBucket    源桶
   * @param sourceObjectKey 源文件key
   * @param bucket          桶
   * @param objectKey       文件key
   * @return 新文件url
   */
  public String copyFile(String sourceBucket, String sourceObjectKey, String bucket, String objectKey) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      CopySource source = CopySource.builder().bucket(sourceBucket).object(sourceObjectKey).build();
      client.copyObject(CopyObjectArgs.builder().bucket(bucket).object(objectKey).source(source).build());
      return getObjectPrefixUrl(bucket) + objectKey;
  }
 
  /**
   * 删除文件
   *
   * @param bucket    桶
   * @param objectKey 文件key
   */
  public void deleteFile(String bucket, String objectKey) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build());
  }
 
  /**
   * 获取文件签名url
   *
   * @param bucket    桶
   * @param objectKey 文件key
   * @param expires   签名有效时间  单位秒
   * @return 文件签名地址
   */
  public String getSignedUrl(String bucket, String objectKey, int expires) throws Exception {
      MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
      return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucket).object(objectKey).expiry(expires).build());
  }
 }