简介
- MinIO 是在 Apache License v2.0 下发布的对象存储服务器。 它与 Amazon S3 云存储服务兼容。 它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM 映像。 对象的大小可以从几 KB 到最大 5TB。
- MinIO 服务器足够轻,可以与应用程序堆栈捆绑在一起,类似于 NodeJS,Redis 和 MySQL
- 一种高性能的分布式对象存储服务器,用于大型数据基础设施。它是机器学习和其他大数据工作负载下Hadoop HDFS 的理想 s3 兼容替代品
安装(2021-04-18T19-26-29Z)
docker pull minio/minio:RELEASE.2021-04-18T19-26-29Z
运行MinIO 自定义 Access(至少三位) 和 Secret (至少8位)密钥要覆盖 MinIO 的自动生成的密钥,将 Access 和 Secret 密钥设为环境变量。MinIO 允许常规字符串作为 Access 和 Secret 密钥
docker run -p 9000:9000 --name=cg_minio -d --restart=always -e "MINIO_ACCESS_KEY=cgadmin" -e "MINIO_SECRET_KEY=cgadmin2022" -v /root/minio/data:/data -v /root/minio/config:/root/.minio minio/minio:RELEASE.2021-04-18T19-26-29Z server /data
登录:
http://192.168.220.130:9000
springboot整合minio
导入依赖
io.miniominio8.0.3
修改配置文件
spring:# 配置文件上传大小限制servlet:multipart:max-file-size: 200MBmax-request-size: 200MB
minio:endpoint: http://192.168.220.110:9000accessKey: cgadminsecretKey: cgadmin2022secure: falseimgSize: 1024 # 图片大小限制,单位:mfileSize: 1024 # 文件大小限制,单位:mshareBucketName: pet-photo-bucketvideoShareBucketName: pet-video-bucket# 雪花算法配置
code:worker_id: 2datacenter_id: 22
配置实体类
@Component
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties{/*** 是否开启*/private Boolean enabled;/*** 存储对象服务器类型*/private OssType type;/*** OSS 访问端点,集群时需提供统一入口*/private String endpoint;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;}
存储对象服务器枚举
@Getter
@AllArgsConstructor
public enum OssType {/*** Minio 对象存储*/MINIO("minio", 1),/*** 华为 OBS*/OBS("obs", 2),/*** 腾讯 COS*/COS("tencent", 3),/*** 阿里巴巴 SSO*/ALIBABA("alibaba", 4),;/*** 名称*/final String name;/*** 类型*/final int type;
}
配置类
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({MinioClient.class})
@EnableConfigurationProperties({MinioProperties.class, CodeProperties.class})
@ConditionalOnExpression("${minio.enabled}")
@ConditionalOnProperty(value = "minio.type", havingValue = "minio")
public class MinioConfiguration {@Bean@SneakyThrows@ConditionalOnMissingBean(MinioClient.class)public MinioClient minioClient(MinioProperties minioProperties) {return MinioClient.builder().endpoint(minioProperties.getEndpoint()).credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()).build();}@Bean@ConditionalOnBean({MinioClient.class})@ConditionalOnMissingBean(MinioUtil.class)public MinioUtil minioUtil(MinioClient minioClient, MinioProperties minioProperties, CodeProperties codeProperties) {return new MinioUtil(minioClient, minioProperties,codeProperties);}}
工具类
@Slf4j
@AllArgsConstructor
public class MinioUtil {/*** MinIO 客户端*/private MinioClient minioClient;/*** MinIO 配置类*/private MinioProperties minioProperties;/*** 订单号*/private CodeProperties codeProperties;/*** 查询所有存储桶** @return Bucket 集合*/@SneakyThrowspublic List listBuckets() {return minioClient.listBuckets();}/*** 桶是否存在** @param bucketName 桶名* @return 是否存在*/@SneakyThrowspublic boolean bucketExists(String bucketName) {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());}/*** 创建存储桶** @param bucketName 桶名*/@SneakyThrowspublic void makeBucket(String bucketName) {if (!bucketExists(bucketName)) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}/*** 删除一个空桶 如果存储桶存在对象不为空时,删除会报错。** @param bucketName 桶名*/@SneakyThrowspublic void removeBucket(String bucketName) {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/*** description: 上传文件** @author: CG* @date: 2022/4/20* @params:* @Param multipartFile:* @Param bucketName:* @return:* @return: java.lang.String*/@SneakyThrowspublic String pullObject(MultipartFile multipartFile, String bucketName) {String fileExt = FileUtil.extName(multipartFile.getOriginalFilename());String uuidFileName = generateOssUuidFileName(fileExt);InputStream inputStream = multipartFile.getInputStream();String fileType = multipartFile.getContentType();System.out.println(fileExt + "--" + fileType);try {Assert.isTrue(bucketExists(bucketName), "桶不存在");minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(uuidFileName).stream(inputStream, inputStream.available(), -1).contentType(fileType).build());return StrUtil.SLASH + bucketName + StrUtil.SLASH + uuidFileName;} finally {inputStream.close();}}/*** 返回临时带签名、过期时间一天、Get请求方式的访问URL** @param bucketName 桶名* @param ossFilePath Oss文件路径* @return*/@SneakyThrowspublic String getPresignedObjectUrl(String bucketName, String ossFilePath) {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(ossFilePath).expiry(60 * 60 * 24).build());}/*** GetObject接口用于获取某个文件(Object)。此操作需要对此Object具有读权限。** @param bucketName 桶名* @param ossFilePath Oss文件路径*/@SneakyThrowspublic InputStream getObject(String bucketName, String ossFilePath) {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(ossFilePath).build());}/*** 查询桶的对象信息** @param bucketName 桶名* @param recursive 是否递归查询* @return*/@SneakyThrowspublic Iterable> listObjects(String bucketName, boolean recursive) {return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).recursive(recursive).build());}/*** 生成随机文件名,防止重复** @return*/public String generateOssUuidFileName(String fileExt) {Snowflake snowflake = IdUtil.getSnowflake(codeProperties.getWorkerId(), codeProperties.getDatacenterId());String resourceCodeNum = snowflake.nextIdStr();returnDateUtil.format(new Date(), "yyyy/MM/dd") +StrUtil.SLASH +resourceCodeNum +StrUtil.C_DOT +fileExt;}/*** 获取带签名的临时上传元数据对象,前端可获取后,直接上传到Minio** @param bucketName* @param fileName* @return*/@SneakyThrowspublic Map getPresignedPostFormData(String bucketName, String fileName) {// 为存储桶创建一个上传策略,过期时间为7天PostPolicy policy = new PostPolicy(bucketName, ZonedDateTime.now().plusDays(7));// 设置一个参数key,值为上传对象的名称policy.addEqualsCondition("key", fileName);// 添加Content-Type以"image/"开头,表示只能上传照片policy.addStartsWithCondition("Content-Type", "image/");// 设置上传文件的大小 64kiB to 10MiB.policy.addContentLengthRangeCondition(64 * 1024, 10 * 1024 * 1024);return minioClient.getPresignedPostFormData(policy);}}
service
public void upResource(String resourceDescribe, MultipartFile multipartFile, String bucketName) {String resourcePath = minioUtil.pullObject(multipartFile, bucketName);Assert.notEmpty(resourcePath, "资源上传失败");}
controller
@PostMapping(value = "{bucket-name}", headers = "content-type=multipart/form-data")@ApiOperation(value = "资源上传", response = ResultDTO.class)@ApiImplicitParams({@ApiImplicitParam(value = "资源描述", name = "resourceDescribe", required = true, paramType = "query", dataType = "String"),@ApiImplicitParam(value = "minio桶名称", name = "bucket-name", required = true, paramType = "path", dataType = "String"),})public ResultDTO resourceUp(@NotNull String resourceDescribe, @NotNull @ApiParam(name = "multipartFile", value = "资源文件", required = true) MultipartFile multipartFile, @PathVariable("bucket-name") @NotNull String bucketName) {service.upResource(resourceDescribe, multipartFile, bucketName);return ResultDTO.success();}