work文档格式,后面再调整
MinIO 使用文档
下载安装
官网下载地址:https://min.io/download
注:本文档使用的目录和ip要根据自己项目设置
单机部署
1.创建目录
1.1创建保存minio目录
mkdir -p /minio
1.2创建启动目录
mkdir -p /minio/bin/
1.3创建minio bucket目录,即上传文件保存目录
mkdir -p /minio/data
2.创建启动脚本
start.sh
#!/bin/bash
#设置用户名和密码
export MINIO_ACCESS_KEY=panys
export MINIO_SECRET_KEY=panys123456
#设置端口 --address ip:port
#后台启动
nohup /minio/minio server --address 192.168.201.149:9002 /minio/data/ > /minio/logs/minio.log 2>&1 &
3.创建停止脚本
#!/bin/bash
#停止 stop
ps -ef | grep -w minio | grep -v grep | awk '{print $2}'|xargs kill -9
4.授权
4.1授权minio文件
chmod +x minio
4.2给脚本start.sh和stop.sh授权
chmod+x start.sh stop.sh
5.启动测试
运行启动脚本
./minio/bin/start.sh
在浏览器上输入访问地址http://192.168.201.149:9002,测试创建bucket和上传文件
显示上图代表单机部署成功
集群部署
因为官方推荐集群部署需要四个节点,所以本文档使用两台机器,每台机器两个磁盘模式部署
192.168.201.149 /minio/data /minio/data2
192.168.201.150 /minio/data /minio/data2
1.创建目录
1.1创建保存minio目录
mkdir -p /minio
上传下载的minio文件到minio目录
1.2创建启动目录
mkdir -p /minio/bin/
1.3创建minio bucket目录
即上传文件保存目录,两台机器都需要创建
mkdir -p /minio/{data,data2}
2.创建启动脚本
start.sh
#!/bin/bash
#设置用户名和密码
export MINIO_ACCESS_KEY=panys
export MINIO_SECRET_KEY=panys123456
#修改访问 --address ip:port
#后台启动
nohup /minio/minio server --address 0.0.0.0:9002 http://192.168.201.149/minio/data http://192.168.201.149/minio/data2 http://192.168.201.150/minio/data http://192.168.201.150/minio/data2 > /minio/logs/minio.log 2>&1 &
3.创建停止脚本
stop.sh
#!/bin/bash
#停止 stop
ps -ef | grep -w minio | grep -v grep | awk '{print $2}'|xargs kill -9
4.授权
两台机器都需要执行
4.1授权minio文件
chmod +x minio
4.2给脚本start.sh和stop.sh授权
chmod+x start.sh stop.sh
5.启动测试
两台机器运行启动脚本
./minio/bin/start.sh
在浏览器上输入访问地址http://192.168.201.149:9002,测试创建bucket和上传文件
在浏览器上输入访问地址http://192.168.201.150:9002,如果有相同的文件则集群部署minio成功。
Nginx代理
minio集群部署,提供统一访问路径,可以使用nginx配置负载均衡
如下:
upstream minio{
server 192.168.201.149:9002;
server 192.168.201.150:9002;
}
server {
listen 9002;
server_name minio;
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;
}
}
整合springboot 2.x API
Java client API 官方文档
https://docs.min.io/docs/java-client-quickstart-guide.html
说明:minio从7.0.2版本后开始变化,API有所区别,规范了参数
配置文件yaml
# minio 配置,endpoint访问路径,accessKey 用户名,secretKey 密码,bucketName 存储桶
min:
io:
endpoint: http://192.168.201.148:9002
accessKey: aaa
secretKey: aaa123456
bucketName: test
旧版
引入maven文件
旧版:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
新版:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
工具类
MinIoProperties
package cn.emd.platform.common.file.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* MinIo实体参数类
*
* @author pan
* @date 2021/4/26
*/
@Data
@Component
@ConfigurationProperties(prefix = "min.io")
public class MinIoProperties {
/**
* 访问地址
*/
private String endpoint;
/**
* 用户名
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 存储桶
*/
private String bucketName="pan";
}
特殊参数说明
objectName存储桶的文件名,可以是文件,也可以是文件夹+文件
例如:Entity.vm或者pan/Entity.vm
filename 文件所在地址,上传文件时文件所在位置地址
例如:D://Entity.vm
fileName 文件保存地址,下载时保存文件位置地址
例如:D://pan/entity.vm
旧版工具类
MinIoUtils
package cn.emd.platform.common.file.util;
import cn.emd.platform.common.core.exception.DynamicException;
import cn.emd.platform.common.file.config.MinIoProperties;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import io.minio.errors.*;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.InputStream;
/**
* MinIo工具类
*
* @author pan
* @date 2021/4/25
*/
@Component
@Configuration
@EnableConfigurationProperties(MinIoProperties.class)
public class MinIoUtils {
private MinIoProperties minIoProperties;
private MinioClient minioClient;
public MinIoUtils(MinIoProperties minIoProperties){
this.minIoProperties=minIoProperties;
}
@PostConstruct
public void init(){
try {
minioClient=new MinioClient(minIoProperties.getEndpoint(),
minIoProperties.getAccessKey(),
minIoProperties.getSecretKey());
//创建一个默认的bucket
boolean found =this.bucketExists(minIoProperties.getBucketName());
if (!found) {
this.makeBucket(minIoProperties.getBucketName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 判断是否存在 bucket
* @param bucketName 存储桶
* @return 存在true,不存在false
*/
public Boolean bucketExists(String bucketName){
try {
return minioClient.bucketExists(bucketName);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 创建bucket
*
* @author pan
* @date 2021/4/26
*/
public void makeBucket(String bucketName){
try {
if(bucketExists(bucketName)){
throw new DynamicException(bucketName+"已存在");
}
minioClient.makeBucket(bucketName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 使用默认的存储桶bucket
*
* @author pan
* @date 2021/4/26
*/
public String useDefaultBucket(String bucketName){
if(StringUtils.isBlank(bucketName)){
bucketName=minIoProperties.getBucketName();
}
return bucketName;
}
/**
* 上传文件(地址方式)
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param filename 文件+路径
* @return 文件保存位置
*/
@SneakyThrows
public String uploadFile(String bucketName,String objectName,String filename){
//如果存储桶为空,则使用默认的
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.putObject(bucketName,objectName,filename,null);
return objectName;
}
/**
* 上传文件
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param multipartFile 文件流
* @return 文件保存位置
*/
@SneakyThrows
public String uploadFile(String bucketName, String objectName, MultipartFile multipartFile){
//如果存储桶为空,则使用默认的
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
InputStream inputStream=multipartFile.getInputStream();
PutObjectOptions putObjectOptions=new PutObjectOptions(multipartFile.getSize(),-1L);
minioClient.putObject(bucketName,objectName,inputStream,putObjectOptions);
return objectName;
}
/**
* 删除文件
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @return 文件保存位置
*/
@SneakyThrows
public String deleteFile(String bucketName, String objectName){
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.removeObject(bucketName,objectName);
return objectName;
}
/**
* 下载文件
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param fileName 文件保存位置
* @return 文件保存位置
*/
@SneakyThrows
public String downloadFile(String bucketName, String objectName,String fileName){
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.getObject(bucketName,objectName,fileName);
return fileName;
}
/**
* 下载文件
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @return 文件保存位置
*/
@SneakyThrows
public InputStream downloadFile(String bucketName, String objectName){
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
return minioClient.getObject(bucketName,objectName);
}
}
新版工具类
MinIoUtil
package cn.emd.platform.common.file.util;
import cn.emd.platform.common.core.exception.DynamicException;
import cn.emd.platform.common.file.config.MinIoProperties;
import io.minio.*;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.InputStream;
/**
* MinIo工具类
*
* @author pan
* @date 2021/4/27
*/
@Component
@Configuration
@EnableConfigurationProperties(MinIoProperties.class)
public class MinIoUtil {
private MinIoProperties minIoProperties;
private MinioClient minioClient;
public MinIoUtil(MinIoProperties minIoProperties){
this.minIoProperties=minIoProperties;
}
@PostConstruct
public void init(){
minioClient=MinioClient.builder()
.endpoint(minIoProperties.getEndpoint())
.credentials(minIoProperties.getAccessKey(),minIoProperties.getSecretKey())
.build();
//创建默认一个bucket,即存储桶
try {
boolean found =this.bucketExists(minIoProperties.getBucketName());
if (!found) {
this.makeBucket(minIoProperties.getBucketName());
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 判断是否存在 bucket
* @param bucketName 存储桶
* @return 存在true,不存在false
*/
public Boolean bucketExists(String bucketName){
try {
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 创建bucket
*
* @author pan
* @date 2021/4/26
*/
public void makeBucket(String bucketName){
try {
if(this.bucketExists(bucketName)){
throw new DynamicException(bucketName+"已存在");
}
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 使用默认的存储桶bucket
*
* @author pan
* @date 2021/4/26
*/
public String useDefaultBucket(String bucketName){
if(StringUtils.isBlank(bucketName)){
bucketName=minIoProperties.getBucketName();
}
return bucketName;
}
/**
* 上传文件(浏览器方式)
*
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param multipartFile 文件流
* @return 文件保存位置
*/
@SneakyThrows
public String uploadFile(String bucketName, String objectName, MultipartFile multipartFile) {
//如果存储桶为空,则使用默认的
bucketName=useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
InputStream inputStream = multipartFile.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(inputStream,multipartFile.getSize(),-1L)
.build());
return objectName;
}
/**
* 上传文件(地址方式)
*
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param filename 文件地址
* @return 文件保存位置
*/
@SneakyThrows
public String uploadFile(String bucketName, String objectName, String filename) {
//如果存储桶为空,则使用默认的
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.uploadObject(UploadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(filename)
.build()
);
return objectName;
}
/**
* 下载文件
*
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @param fileName 文件保存位置
* @return 文件保存位置
*/
@SneakyThrows
public String downloadFile(String bucketName, String objectName, String fileName) {
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.downloadObject(DownloadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(fileName)
.build()
);
return fileName;
}
/**
* 下载文件
*
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @return 文件流
*/
@SneakyThrows
public InputStream downloadFile(String bucketName, String objectName) {
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
InputStream inputStream=minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
return inputStream;
}
/**
* 删除文件
*
* @param bucketName 存储桶名称
* @param objectName 保存在存储桶的文件
* @return 文件保存位置
*/
@SneakyThrows
public String deleteFile(String bucketName, String objectName) {
bucketName = useDefaultBucket(bucketName);
if (!this.bucketExists(bucketName)) {
throw new DynamicException(bucketName + "存储桶不存在");
}
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
return objectName;
}
}