简介
MinIO是在Apache License v2.0下发布的对象存储服务器。它与Amazon S3云存储服务兼容。它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM映像。对象的大小可以从几KB到最大5TB。
优点
- 使用Minio Erasure Code,即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。
- 兼容Amazon S3
- 高度可用
- 直接覆盖重名文件
- 可以对接后端存储
- 轻量级,获得多种语言(java、python等)的sdk支持
- 加密和防篡改
缺点
- 前端直连Minio上传文件时,不能获得进度信息
- 不支持动态增加节点
MINIO上传下载
MINIO管理界面
- 新的版本我们访问9000端口,他会自动为我们转到控制台
- 首页界面我们可以查看所有的桶数量、内容所占内存、以及MINIO的驱动信息等
- 平时我们主要关注Buckets中的信息,这里面存放着我们上传的所有文件
- 还提供了管理用户、组以及查看日志的功能
MINIO上传、下载
- 我们在上传时要指定一个bucket,但是这个桶有可能存在也可能不存在,所以我们要先判断以下,不存在则新建、存在则直接添加
- 在创建桶时,我们需要注意,这个桶默认是没有对外访问权限的,即你不能直接根据路径访问,需要设置一下访问策略
- 策略格式如下,Action中的配置表示可以接受的行为,Resource表示对哪个资源实行该策略
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [ // 可以做出的行动(权限)
"s3:ListAllMyBuckets", // 查看所有的“桶”列表
"s3:ListBucket", // 查看桶内的对象列表
"s3:GetObject", // 下载对象
"s3:PutObject", // 上传对象
"s3:DeleteObject" // 删除对象
],
"Resource": [
"arn:aws:s3:::*" // (应用到的资源,*表示所有,也可以用路径来控制范围。arn:aws:s3是命名空间)
]
}
]
}
- 设置好访问策略之后,我们可以直接通过路径访问文件
代码
@Data
@ConfigurationProperties(prefix = "custom.minio")
public class MinioProperties {
// url
private String url;
// 是否启用证书 https
private boolean secure;
// 用户名
private String accessKey;
// 密码
private String secureKey;
}
@Configuration
@ConditionalOnProperty(prefix = "custom.minio", name = "enable", havingValue = "true")
@EnableConfigurationProperties(MinioProperties.class)
public class MinioUtils {
private static MinioProperties properties;
@Autowired
public void setProperties(MinioProperties properties) {
this.properties = properties;
}
//获取Minio文件
public static Response getMinioFile(Map<String,String> urlData) throws Exception {
String minioLoc = properties.getUrl();
String bucket = "clouddefault";
String fileName = "";
if(urlData.containsKey("minioLoc")){
minioLoc=urlData.get("minioLoc");
}
if(urlData.containsKey("bucket")){
bucket=urlData.get("bucket");
}
if(!urlData.containsKey("fileName")){
throw new RuntimeException("缺少文件名信息");
}else{
fileName=urlData.get("fileName");
}
minioLoc=minioLoc.endsWith("/")?minioLoc.substring(0,minioLoc.length()-1):minioLoc;
String url = minioLoc+"/"+bucket+"/"+fileName;
return HttpUtils.doGet(url);
}
//上传
public static Map<String,String> upload(InputStream inputStream) throws Exception {
return upload(inputStream,"");
}
//上传
public static Map<String,String> upload(InputStream inputStream, String contentType) throws Exception {
//默认bucket
String bucket = "clouddefault"; //bucket要小写
//生成随机文件名称
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
return upload(inputStream,contentType,bucket,fileName);
}
//上传
public static Map<String,String> upload(InputStream inputStream, String contentType, String bucket, String fileName) throws Exception {
ObjectWriteResponse objectWriteResponse = null;
Map<String,String> result =new HashMap<>();
//构建minioClient
MinioClient minioClient = null;
minioClient = MinioClient.builder()
.endpoint(properties.getUrl())
.credentials(properties.getAccessKey(), properties.getSecureKey())
.build();
//检查桶是否存在
checkBucket(minioClient,false,bucket);
PutObjectArgs.Builder stream = createStream(inputStream,contentType,bucket,fileName);
objectWriteResponse = minioClient.putObject(stream.build());
result.put("minioLoc",properties.getUrl());
result.put("bucket",bucket);
result.put("fileName",fileName);
result.put("fileUrl",objectWriteResponse.region());
return result;
}
private static void checkBucket(MinioClient minioClient ,boolean versioning, String bucket) throws Exception {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
//设置Procy属性 设置所有请求都能访问
String config = "{ " +
" \"Id\": \"Policy1\", " +
" \"Version\": \"2012-10-17\", " +
" \"Statement\": [ " +
" { " +
" \"Sid\": \"Statement1\", " +
" \"Effect\": \"Allow\", " +
" \"Action\": [ " +
" \"s3:ListBucket\", " +
" \"s3:GetObject\" " +
" ], " +
" \"Resource\": [ " +
" \"arn:aws:s3:::"+bucket+"\", " +
" \"arn:aws:s3:::"+bucket+"/*\" " +
" ]," +
" \"Principal\": \"*\"" +
" } " +
" ] " +
"}";
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder().bucket(bucket).config(config).build());
}
// 版本控制
VersioningConfiguration configuration = minioClient.getBucketVersioning(GetBucketVersioningArgs.builder().bucket(bucket).build());
boolean enabled = configuration.status() == VersioningConfiguration.Status.ENABLED;
if (versioning && !enabled) {
minioClient.setBucketVersioning(SetBucketVersioningArgs.builder()
.config(new VersioningConfiguration(VersioningConfiguration.Status.ENABLED, null)).bucket(bucket).build());
} else if (!versioning && enabled) {
minioClient.setBucketVersioning(SetBucketVersioningArgs.builder()
.config(new VersioningConfiguration(VersioningConfiguration.Status.SUSPENDED, null)).bucket(bucket).build());
}
}
private static PutObjectArgs.Builder createStream(InputStream inputStream,String contentType,String bucket,String fileName) throws IOException {
if(Strings.isNotBlank(contentType)){
return PutObjectArgs.builder()
.contentType(contentType)
//如果知道对象大小,则将-1传递给partSize进行自动检测;
.stream(inputStream,inputStream.available(),-1)
.bucket(bucket)
.object(fileName); //服务器端存储的文件名
}else{
return PutObjectArgs.builder()
//如果知道对象大小,则将-1传递给partSize进行自动检测;
.stream(inputStream,inputStream.available(),-1)
.bucket(bucket)
.object(fileName); //服务器端存储的文件名
}
}
}