项目是为附件上传/文件上传模块,可以作为熟悉了解Minion文件服务器的项目也可以将本模块直接移植进自己的项目中
SpringBoot2.x + MyBatis3 +MyBatis3-Plus + MySQL8 + Minio(文件服务器) +Swagger2(接口文档框架)
4.0.0
com.zzg
sb-minio
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.1.2.RELEASE
UTF-8
UTF-8
1.8
2.6
1.10
3.9
3.6
2.6
3.2.1
1.8
1.3.1
3.1.0
4.5.2
1.2.48
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-web
io.minio
minio
8.0.0
com.squareup.okhttp3
okhttp
4.9.1
org.jetbrains.kotlin
kotlin-stdlib
1.3.70
com.alibaba
druid-spring-boot-starter
1.1.10
mysql
mysql-connector-java
runtime
io.springfox
springfox-swagger2
2.7.0
io.springfox
springfox-swagger-ui
2.7.0
cn.smallbun.screw
screw-core
1.0.5
org.freemarker
freemarker
2.3.30
org.projectlombok
lombok
com.baomidou
mybatis-plus-boot-starter
3.4.1
org.springframework.boot
spring-boot-starter-validation
com.fasterxml.jackson.core
jackson-annotations
2.9.0
commons-lang
commons-lang
${commons-lang.version}
org.apache.commons
commons-lang3
${commons-lang3.version}
commons-codec
commons-codec
${commons-codec.version}
commons-net
commons-net
${commons-net.version}
commons-io
commons-io
${commons-io.version}
commons-collections
commons-collections
${commons-collections.version}
commons-fileupload
commons-fileupload
${common-fileupload.version}
org.apache.commons
commons-text
${commons-text.version}
javax.servlet
javax.servlet-api
${servlet-api.version}
org.apache.httpcomponents
httpclient
${httpclient.version}
com.alibaba
fastjson
${fastjson.version}
CREATE TABLE `upload_file` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件名称',
`file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件路径',
`file_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件类型',
`file_size` int(11) NULL DEFAULT NULL COMMENT '文件大小',
`file_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件描述',
`created_by` int(11) NULL DEFAULT NULL COMMENT '创建人',
`created_dt` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
com.zzg.entity.UploadFile.java
com.zzg.mapper.UploadFileMapper.java
com.zzg.service.UploadFileService.java
com.zzg.service.impl.UploadFileServiceImpl.java
mapper/UploadFileMapper.xml
package com.zzg.minio.core;
import java.io.InputStream;
/**
* minio 核心接口服务定义
* @author zzg
*
*/
public interface MinioUploadInteface {
/**
*
* @Title: uploadFile
* @Description: 文件上传
* @param: @param file
* @param: @param bucket
* @param: @param contentType
* @param: @param suffix
* @param: @return
* @return: String
* @throws
*/
String uploadFile(InputStream stream, String bucket, String contentType, String suffix);
/**
*
* @Title: removeFile
* @Description: 文件删除
* @param: @param objectKey
* @param: @param bucket
* @param: @return
* @return: String
* @throws
*/
boolean removeFile(String objectKey, String bucket);
/**
*
* @Title: downloadFile
* @Description: 文件下载
* @param: @param objectKey
* @param: @param bucket
* @param: @return
* @return: File
* @throws
*/
InputStream downloadFile(String objectKey, String bucket);
/**
*
* @Title: createBucket
* @Description: 创建桶,并指定桶策略
* @param: @param bucket
* @param: @param policy
* @param: @return
* @return: boolean
* @throws
*/
boolean createBucket(String bucket);
/**
*
* @Title: removeBucket
* @Description: 移除指定桶
* @param: @param bucket
* @param: @return
* @return: boolean
* @throws
*/
boolean removeBucket(String bucket);
/**
*
* @Title: setBucketPolicy
* @Description: 设置桶策略
* @param: @param bucket
* @param: @param policy
* @param: @return
* @return: boolean
* @throws
*/
boolean setBucketPolicy(String bucket, String policy);
}
package com.zzg.minio.entity;
import java.io.Serializable;
/**
* minio 服务器连接实体对象定义
* @author zzg
*
*/
@SuppressWarnings("serial")
public class MinioUploadEntity implements Serializable {
private String url = "";
private String access = "";
private String secret = "";
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getAccess() {
return access;
}
public void setAccess(String access) {
this.access = access;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public MinioUploadEntity(String url, String access, String secret) {
super();
this.url = url;
this.access = access;
this.secret = secret;
}
}
package com.zzg.minio.policy;
import io.minio.MinioClient;
/**
* minio 桶策略接口
* @author zzg
*
*/
public interface BucketPolicyInterface {
/**
*
* @Title: createBucketPolicy
* @Description: 设置桶策略
* @param: @param client
* @param: @param bucket
* @param: @return
* @return: boolean
* @throws
*/
boolean createBucketPolicy(MinioClient client, String bucket);
}
package com.zzg.minio.policy.impl;
import com.zzg.minio.policy.BucketPolicyInterface;
import io.minio.MinioClient;
/**
* Minio 桶 默认策略
* @author zzg
*
*/
public class BuckerDefaultPolicy implements BucketPolicyInterface {
@Override
public boolean createBucketPolicy(MinioClient client, String bucket) {
// TODO Auto-generated method stub
return false;
}
}
package com.zzg.minio.policy.impl;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zzg.minio.policy.BucketPolicyInterface;
import io.minio.MinioClient;
import io.minio.SetBucketPolicyArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
/**
* Minio 桶 读策略
* @author zzg
*
*/
public class BuckerReadPolicy implements BucketPolicyInterface {
// 日志记录
public static final Logger logger = LoggerFactory.getLogger(BuckerReadPolicy.class);
/**
* 桶占位符
*/
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 + "/*\"]}]}";
@Override
public boolean createBucketPolicy(MinioClient client, String bucket) {
// TODO Auto-generated method stub
try {
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket)
.config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
return true;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
}
package com.zzg.minio.policy.impl;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zzg.minio.policy.BucketPolicyInterface;
import io.minio.MinioClient;
import io.minio.SetBucketPolicyArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
/**
* Minio 桶 读写策略
* @author zzg
*
*/
public class BuckerReadWriterPolicy implements BucketPolicyInterface {
// 日志记录
public static final Logger logger = LoggerFactory.getLogger(BuckerReadWriterPolicy.class);
/**
* 桶占位符
*/
private static final String BUCKET_PARAM = "${bucket}";
/**
* 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 + "/*\"]}]}";
@Override
public boolean createBucketPolicy(MinioClient client, String bucket) {
// TODO Auto-generated method stub
try {
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
return true;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
}
package com.zzg.minio.policy.impl;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zzg.minio.policy.BucketPolicyInterface;
import io.minio.MinioClient;
import io.minio.SetBucketPolicyArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
/**
* Minio 桶 写策略
* @author zzg
*
*/
public class BuckerWritePoliy implements BucketPolicyInterface {
// 日志记录
public static final Logger logger = LoggerFactory.getLogger(BuckerWritePoliy.class);
/**
* 桶占位符
*/
private static final String BUCKET_PARAM = "${bucket}";
/**
* 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 + "/*\"]}]}";
@Override
public boolean createBucketPolicy(MinioClient client, String bucket) {
// TODO Auto-generated method stub
try {
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket)
.config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
return true;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
}
package com.zzg.minio.policy.content;
/**
* minio 常量属性定义
* @author zzg
*
*/
public class BuckerPolicyContent {
public static final String READ ="read";
public static final String WRITE ="write";
public static final String READ_WRITE ="read-write";
}
package com.zzg.minio.factory;
import java.util.HashMap;
import java.util.Map;
import com.zzg.minio.policy.BucketPolicyInterface;
import com.zzg.minio.policy.content.BuckerPolicyContent;
import com.zzg.minio.policy.impl.BuckerDefaultPolicy;
import com.zzg.minio.policy.impl.BuckerReadPolicy;
import com.zzg.minio.policy.impl.BuckerReadWriterPolicy;
import com.zzg.minio.policy.impl.BuckerWritePoliy;
/**
* 桶策略工厂
* @author zzg
*
*/
public class BuckerPolicyFactory {
static Map operationMap = new HashMap<>();
static {
operationMap.put(BuckerPolicyContent.READ, new BuckerReadPolicy());// 只读
operationMap.put(BuckerPolicyContent.WRITE, new BuckerWritePoliy());// 只写
operationMap.put(BuckerPolicyContent.READ_WRITE, new BuckerReadWriterPolicy());// 读写
}
public static BucketPolicyInterface getBucketPolicyInterface(String poliy){
BucketPolicyInterface object = operationMap.get(poliy);
if(object == null){
object = new BuckerDefaultPolicy();
}
return object;
}
}
package com.zzg.minio.util;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zzg.common.util.UUIDUtils;
import com.zzg.minio.core.MinioUploadInteface;
import com.zzg.minio.entity.MinioUploadEntity;
import com.zzg.minio.factory.BuckerPolicyFactory;
import com.zzg.minio.policy.BucketPolicyInterface;
import io.minio.BucketExistsArgs;
import io.minio.GetObjectArgs;
import io.minio.GetObjectResponse;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.http.Method;
import io.minio.messages.Bucket;
/**
* Minio 封装工具类方法:包含桶创建、删除、文件上传、文件预览、文件下载、文件删除等相关基础功能
* @author zzg
*
*/
public class MinioUploadUtil implements MinioUploadInteface {
// 日志记录
public static final Logger logger = LoggerFactory.getLogger(MinioUploadUtil.class);
private MinioUploadEntity entity;
public MinioUploadEntity getEntity() {
return entity;
}
public void setEntity(MinioUploadEntity entity) {
this.entity = entity;
}
public MinioUploadUtil(MinioUploadEntity entity) {
super();
this.entity = entity;
}
public MinioClient createMinioClient(){
//创建MinioClient对象
MinioClient minioClient = MinioClient.builder()
.endpoint(entity.getUrl())
.credentials(entity.getAccess(), entity.getSecret())
.build();
return minioClient;
}
@Override
public String uploadFile(InputStream stream, String bucket, String contentType, String suffix) {
// TODO Auto-generated method stub
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
// 生成文件上传唯一名称
String objectKey =UUIDUtils.getUUID().concat(".").concat(suffix);
// 文件流上传
try {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectKey).stream(stream, stream.available(), -1).contentType(contentType).build());
// 返回文件上传的唯一标识
return objectKey;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return null;
}
@Override
public boolean removeFile(String objectKey, String bucket) {
// TODO Auto-generated method stub
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build());
return true;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
@Override
public GetObjectResponse downloadFile(String objectKey, String bucket) {
// TODO Auto-generated method stub
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
try {
// 返回文件流
GetObjectResponse response = minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
System.out.print("Headers:--------"+ response.headers().toString());
return response;
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IllegalArgumentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return null;
}
/**
* 生成上传图片预览地址
* @param objectKey
* @param bucket
* @return
* @throws InvalidKeyException
* @throws ErrorResponseException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidResponseException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws ServerException
* @throws IllegalArgumentException
* @throws IOException
*/
public String getPreviewAddress(String objectKey, String bucket) throws InvalidKeyException, ErrorResponseException, InsufficientDataException, InternalException, InvalidResponseException, NoSuchAlgorithmException, XmlParserException, ServerException, IllegalArgumentException, IOException{
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucket).object(objectKey).build());
}
public List getBucketName(){
List list = new ArrayList();
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
List bucketList = null;
try {
bucketList = minioClient.listBuckets();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ErrorResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InsufficientDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InternalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Bucket bucket : bucketList) {
System.out.println(bucket.creationDate() + ", " + bucket.name());
list.add(bucket.name());
}
return list;
}
@Override
public boolean createBucket(String bucket) {
// TODO Auto-generated method stub
boolean target = false;
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
// 判断桶是否存在
BucketExistsArgs exist = BucketExistsArgs.builder().bucket(bucket).build();
try {
boolean result = minioClient.bucketExists(exist);
if(!result){
MakeBucketArgs create =MakeBucketArgs.builder().bucket(bucket).build();
minioClient.makeBucket(create);
target = true;
}
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (ErrorResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (InsufficientDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (InternalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (InvalidResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (ServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (XmlParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return target;
}
@Override
public boolean removeBucket(String bucket) {
// TODO Auto-generated method stub
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
// 判断桶是否存在
BucketExistsArgs exist = BucketExistsArgs.builder().bucket(bucket).build();
try {
boolean result = minioClient.bucketExists(exist);
if(result){
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
return true;
}
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
@Override
public boolean setBucketPolicy(String bucket, String policy) {
// TODO Auto-generated method stub
//创建MinioClient对象
MinioClient minioClient = this.createMinioClient();
// 判断桶是否存在
BucketExistsArgs exist = BucketExistsArgs.builder().bucket(bucket).build();
try {
boolean result = minioClient.bucketExists(exist);
if(result){
BucketPolicyInterface bucketPolicy = BuckerPolicyFactory.getBucketPolicyInterface(policy);
return bucketPolicy.createBucketPolicy(minioClient, bucket);
}
} catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
| InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
| IOException e) {
// TODO Auto-generated catch block
logger.error("error: {}", e.getMessage(), e);
}
return false;
}
}
MiniO 文件服务器相关资料
Minio 开发者文档:https://docs.min.io/docs/
Windows 搭建Minion:https://blog.csdn.net/zhouzhiwengang/article/details/115542399
链接:https://pan.baidu.com/s/1SaiUE36p8YTyDAuP_970Nw
提取码:1234