1.配置MinIo
@Data
@Configuration
@ConfigurationProperties(prefix="minio")
public class MinIoConfig {
/**
* 访问密钥
*/
private String accessKey;
/**
* 密钥
*/
private String secretKey;
/**
* 访问Url
*/
private String url;
/**
* 捅名称
*/
private String bucketName;
/**
* 创建MinIo客户端
*
* @return
*/
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.build();
}
}
2.工具类
@Slf4j
@Component
public class MinIoUtil {
@Autowired
private MinIoConfig minIoConfig;
@Autowired
private MinioClient minioClient;
/**
* 判断桶是否存在
* @param name
*/
public Boolean existBucket(String name) {
boolean exists;
try{
exists = minioClient.bucketExists(
BucketExistsArgs.builder()
.bucket(name)
.build());
if (!exists) {
minioClient.makeBucket(
MakeBucketArgs.builder().
bucket(minIoConfig.getBucketName())
.build());
}
}catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.BUCKET_NOT_EXIST.getCode(), AppHttpCodeEnum.BUCKET_NOT_EXIST.getMsg());
}
return exists;
}
/**
* 创建存储桶
* @param bucketName
* @return
*/
public Boolean makeBucket(String bucketName) {
if (existBucket(bucketName)) {
try {
minioClient.makeBucket(
MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
} else {
return false;
}
}
/**
* 删除存储桶
* @param bucketName
* @return
*/
public Boolean removeBucket(String bucketName) {
if (existBucket(bucketName)) {
try {
minioClient.removeBucket(
RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
return false;
}
/**
* 列出一个桶中的所有文件目录和大小信息
* @param bucketName
* @return
*/
public List<ObjectItem> getListFiles(String bucketName){
if (existBucket(bucketName)) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.recursive(true)
.build());
List<ObjectItem> objectItems = new ArrayList<>();
results.forEach(result->{
try{
Item item = result.get();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String fileSize = getFileSize(item.size());
String url = minIoConfig.getUrl() + "/" + bucketName + "/" + item.objectName();
ObjectItem objectItem = ObjectItem.builder()
.objectName(item.objectName())
.directory(item.isDir())
.lastModified(item.lastModified()
.format(dateTimeFormatter))
.size(fileSize)
.url(url)
.build();
objectItems.add(objectItem);
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getCode(), AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getMsg());
}
});
return objectItems;
}
return null;
}
/**
* 获取文件夹下所有对象
* @param bucketName
* @return
*/
public List<ObjectItem> getObjectsByDir(String bucketName, String groupName) {
if (existBucket(bucketName)) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.prefix(groupName)
.bucket(bucketName)
.recursive(true)
.build());
List<ObjectItem> objectItems = new ArrayList<>();
results.forEach(result->{
try{
Item item = result.get();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String fileSize = getFileSize(item.size());
String url = minIoConfig.getUrl() + "/" + bucketName + "/" + item.objectName();
ObjectItem objectItem = ObjectItem.builder()
.objectName(item.objectName())
.directory(item.isDir())
.lastModified(item.lastModified()
.format(dateTimeFormatter))
.size(fileSize)
.url(url)
.build();
objectItems.add(objectItem);
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getCode(), AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getMsg());
}
});
return objectItems;
}
return null;
}
/**
* 复制文件夹下所有对象到另一文件夹中
* @param bucketName
* @param groupName
* @param newGroupName
* @return
*/
public void copyObjectByDir(String bucketName, String groupName, String newGroupName) {
if (existBucket(bucketName)) {
List<ObjectItem> objects = getObjectsByDir(bucketName, groupName);
objects.forEach((object->{
String name = object.getObjectName();
String originName = name.substring(name.lastIndexOf('/')+1);
String oldObjectName = groupName + "/" + originName;
String newObjectName = newGroupName + "/" + originName;
try {
//复制文件夹下所有对象到另一文件夹中
minioClient.copyObject(
CopyObjectArgs.builder()
.source(CopySource.builder().bucket(bucketName).object(oldObjectName).build())
.bucket(bucketName)
.object(newObjectName)
.build()
);
//删除原有对象
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(bucketName)
.object(oldObjectName)
.build());
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getCode(), AppHttpCodeEnum.GET_LIST_OBJECTS_ERROR.getMsg());
}
}));
}
}
/**
* 上传文件
* @param file
* @param fileName
*/
public void upload(MultipartFile file, String fileName) {
try {
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs
.builder()
.bucket(minIoConfig.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.UPLOAD_FILE_ERROR.getCode(), AppHttpCodeEnum.UPLOAD_FILE_ERROR.getMsg());
}
}
/**
* 下载文件
* @param fileName
* @return
*/
public ResponseEntity<byte[]> download(String fileName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
//获取对象输入流
in = minioClient.getObject(GetObjectArgs.builder()
.bucket(minIoConfig.getBucketName())
.object(fileName)
.build());
//创建输出流
out = new ByteArrayOutputStream();
//复制流
IOUtils.copy(in, out);
//封装返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(bytes.length);
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.DOWNLOAD_ERROR.getCode(), AppHttpCodeEnum.DOWNLOAD_ERROR.getMsg());
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
return responseEntity;
}
/**
* 删除一个文件夹下所有文件
* @param buckName
* @param groupName
*/
public void removeObjectsByDir(String buckName, String groupName) {
if (existBucket(buckName)) {
try{
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder()
.bucket(buckName)
.prefix(groupName)
.recursive(true)
.build()
);
Iterator<Result<Item>> iterator = results.iterator();
while(iterator.hasNext()) {
Result<Item> itemResult = iterator.next();
Item item = itemResult.get();
String objectName = item.objectName();
System.out.println(objectName);
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(buckName)
.object(objectName)
.build());
}
}catch (Exception e) {
throw new SystemException(AppHttpCodeEnum.MINIO_DEL_ERROR.getCode(), AppHttpCodeEnum.MINIO_DEL_ERROR.getMsg());
}
}
}
/**
* 删除对象(支持批量删除)
* @param bucketName
* @param objects
* @return
*/
public Boolean removeObjects(String bucketName, List<String> objects) {
if (existBucket(bucketName)) {
List<DeleteObject> deleteObjects = objects.stream()
.map(o -> new DeleteObject(o)).collect(Collectors.toList());
Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(deleteObjects)
.build());
try{
for (Result<DeleteError> result : results) {
DeleteError error = result.get();
log.error("MinIo删除错误=>bucketName{},message=>{}", error.bucketName(), error.message());
}
} catch (Exception e) {
log.error("MinIo删除错误异常");
throw new SystemException(AppHttpCodeEnum.MINIO_DEL_ERROR.getCode(), AppHttpCodeEnum.MINIO_DEL_ERROR.getMsg());
}
return true;
}
return false;
}
/**
* 判断对象大小
* @param size
* @return
*/
public static String getFileSize(long size) {
//如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义
if (size < 1024) {
return size + "B";
} else {
size = size / 1024;
}
//如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位
//因为还没有到达要使用另一个单位的时候
//接下去以此类推
if (size < 1024) {
return Math.round(size * 100) / 100 + "KB";
} else {
size = size / 1024;
}
if (size < 1024) {
//因为如果以MB为单位的话,要保留最后1位小数,
//因此,把此数乘以100之后再取余
return Math.round(size * 100) / 100 + "MB";
} else {
//否则如果要以GB为单位的,先除于1024再作同样的处理
return Math.round(size / 1024 * 100) / 100 + "GB";
}
}
}