Files
youlai-boot/src/main/java/com/youlai/system/service/impl/MinioServiceImpl.java
2023-03-01 23:24:07 +08:00

203 lines
6.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.youlai.system.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.youlai.system.pojo.vo.FileInfoVO;
import com.youlai.system.service.FileService;
import io.minio.*;
import io.minio.http.Method;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.time.LocalDateTime;
/**
* MinIO 文件实现类
*
* @author haoxr
* @date 2022/12/17
*/
@Component
@ConfigurationProperties(prefix = "minio")
@Slf4j
public class MinioServiceImpl implements FileService, InitializingBean {
/**
* MinIO的API地址
*/
@Setter
private String endpoint;
/**
* 用户名
*/
@Setter
private String accessKey;
/**
* 密钥
*/
@Setter
private String secretKey;
/**
* 存储桶名称
*/
@Setter
private String bucketName;
/**
* 自定义域名(非必须)
*/
@Setter
private String customDomain;
private MinioClient minioClient;
@Override
public void afterPropertiesSet() {
log.info("MinIO Client init...");
Assert.notBlank(endpoint, "MinIO endpoint can not be null");
Assert.notBlank(accessKey, "MinIO accessKey can not be null");
Assert.notBlank(secretKey, "MinIO secretKey can not be null");
Assert.notBlank(bucketName, "MinIO bucketName can not be null");
this.minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
/**
* 上传文件
*
* @param file 表单文件对象
* @return
*/
@Override
@SneakyThrows
public FileInfoVO uploadFile(MultipartFile file) {
// 存储桶不存在则创建
createBucketIfAbsent(bucketName);
// 生成文件名(日期文件夹)
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
String uuid = IdUtil.simpleUUID();
String fileName = DateUtil.format(LocalDateTime.now(), "yyyy/MM/dd") + "/" + uuid + "." + suffix;
InputStream inputStream = file.getInputStream();
// 文件上传
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.contentType(file.getContentType())
.stream(inputStream, inputStream.available(), -1)
.build();
minioClient.putObject(putObjectArgs);
// 返回文件路径
String fileUrl;
if (StrUtil.isBlank(customDomain)) { // 未配置自定义域名
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName).object(fileName)
.method(Method.GET)
.build();
fileUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
} else { // 配置自定义文件路径域名
fileUrl = customDomain + '/' + bucketName + "/" + fileName;
}
FileInfoVO fileInfoVO = new FileInfoVO();
fileInfoVO.setName(fileName);
fileInfoVO.setUrl(fileUrl);
return fileInfoVO;
}
/**
* 删除文件
*
* @param filePath 文件路径
* https://oss.youlai.tech/default/2022/11/20/test.jpg
* @return
*/
@Override
@SneakyThrows
public boolean deleteFile(String filePath) {
Assert.notBlank(filePath, "删除文件路径不能为空");
String tempStr = "/" + bucketName + "/";
String fileName = filePath.substring(filePath.indexOf(tempStr) + tempStr.length()); // 2022/11/20/test.jpg
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build();
minioClient.removeObject(removeObjectArgs);
return true;
}
/**
* PUBLIC桶策略
* 如果不配置则新建的存储桶默认是PRIVATE则存储桶文件会拒绝访问 Access Denied
*
* @param bucketName
* @return
*/
private static String publicBucketPolicy(String bucketName) {
/**
* AWS的S3存储桶策略
* Principal: 生效用户对象
* Resource: 指定存储桶
* Action: 操作行为
*/
StringBuilder builder = new StringBuilder();
builder.append("{\"Version\":\"2012-10-17\","
+ "\"Statement\":[{\"Effect\":\"Allow\","
+ "\"Principal\":{\"AWS\":[\"*\"]},"
+ "\"Action\":[\"s3:ListBucketMultipartUploads\",\"s3:GetBucketLocation\",\"s3:ListBucket\"],"
+ "\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},"
+ "{\"Effect\":\"Allow\"," + "\"Principal\":{\"AWS\":[\"*\"]},"
+ "\"Action\":[\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\"],"
+ "\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}");
return builder.toString();
}
/**
* 创建存储桶(存储桶不存在)
*
* @param bucketName
*/
@SneakyThrows
private void createBucketIfAbsent(String bucketName) {
BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
if (!minioClient.bucketExists(bucketExistsArgs)) {
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
minioClient.makeBucket(makeBucketArgs);
// 设置存储桶访问权限为PUBLIC 如果不配置则新建的存储桶默认是PRIVATE则存储桶文件会拒绝访问 Access Denied
SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs
.builder()
.bucket(bucketName)
.config(publicBucketPolicy(bucketName))
.build();
minioClient.setBucketPolicy(setBucketPolicyArgs);
}
}
}