package com.artfess.file.util; import com.artfess.base.util.CommonUtil; import com.artfess.base.util.StringUtil; import com.google.common.collect.Multimap; import io.minio.BucketExistsArgs; import io.minio.CreateMultipartUploadResponse; import io.minio.GetObjectArgs; import io.minio.GetPresignedObjectUrlArgs; import io.minio.ListPartsResponse; import io.minio.MakeBucketArgs; import io.minio.MinioClient; import io.minio.ObjectWriteResponse; import io.minio.PutObjectArgs; 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.Part; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; /** * minio文件上传工具类 */ @Slf4j public class MinioUtil { private static String minioUrl; private static String minioName; private static String minioPass; private static String bucketName; public static void setMinioUrl(String minioUrl) { MinioUtil.minioUrl = minioUrl; } public static void setMinioName(String minioName) { MinioUtil.minioName = minioName; } public static void setMinioPass(String minioPass) { MinioUtil.minioPass = minioPass; } public static void setBucketName(String bucketName) { MinioUtil.bucketName = bucketName; } public static String getMinioUrl() { return minioUrl; } public static String getBucketName() { return bucketName; } private static MinioClient minioClient = null; /** * 上传文件 * * @param file 文件 * @param bizPath 路径 * @param fileName 文件名称 * @param customBucket 桶名 * @return 相对路径 */ public static String uploadRelative(MultipartFile file, String bizPath, String fileName, String customBucket) throws Exception { String file_url = ""; String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(newBucket).build(); initMinio(minioUrl, minioName, minioPass); // 检查存储桶是否已经存在 if (minioClient.bucketExists(bucketExistsArgs)) { log.info("Bucket already exists."); } else { // 创建一个名为ota的存储桶 MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(newBucket).build(); minioClient.makeBucket(makeBucketArgs); log.info("create a new bucket as 【" + newBucket + "】!"); } InputStream stream = file.getInputStream(); // 获取文件名 String objectName = ""; if (StringUtils.isEmpty(fileName)) { String orgName = file.getOriginalFilename(); orgName = CommonUtil.getFileName(orgName); if (!bizPath.endsWith("/")) { bizPath = bizPath.concat("/"); } objectName = bizPath + orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf(".")); } else { if (fileName.startsWith("/")) { fileName = fileName.substring(1); } if (!bizPath.endsWith("/")) { bizPath = bizPath.concat("/"); } objectName = bizPath + fileName; } if (objectName.startsWith("/")) { objectName = objectName.substring(1); } // 使用putObject上传一个本地文件到存储桶中。 PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(newBucket) .object(objectName) .stream(stream, stream.available(), -1) .contentType(file.getContentType()) .build(); minioClient.putObject(putObjectArgs); stream.close(); if (!minioUrl.endsWith("/")) { minioUrl = minioUrl.concat("/"); } if (!newBucket.endsWith("/")) { newBucket = newBucket.concat("/"); } if (newBucket.startsWith("/")) { newBucket = newBucket.substring(1); } file_url = newBucket + objectName; return file_url; } /** * 上传文件 * * @param file 文件 * @param bizPath 路径 * @param fileName 文件名称 * @param customBucket 桶名 * @return 文件全路径 */ public static String upload(MultipartFile file, String bizPath, String fileName, String customBucket) throws Exception { String file_url = ""; String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } initMinio(minioUrl, minioName, minioPass); BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(newBucket).build(); // 检查存储桶是否已经存在 if (minioClient.bucketExists(bucketExistsArgs)) { log.info("Bucket already exists."); } else { // 创建一个名为ota的存储桶 MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(newBucket).build(); minioClient.makeBucket(makeBucketArgs); log.info("create a new bucket as 【" + newBucket + "】!"); } InputStream stream = file.getInputStream(); // 获取文件名 String objectName = ""; if (StringUtils.isEmpty(fileName)) { String orgName = file.getOriginalFilename(); orgName = CommonUtil.getFileName(orgName); if (!bizPath.endsWith("/")) { bizPath = bizPath.concat("/"); } objectName = bizPath + orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf(".")); } else { if (fileName.startsWith("/")) { fileName = fileName.substring(1); } if (!bizPath.endsWith("/")) { bizPath = bizPath.concat("/"); } objectName = bizPath + fileName; } if (objectName.startsWith("/")) { objectName = objectName.substring(1); } // 使用putObject上传一个本地文件到存储桶中。 PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(newBucket) .object(objectName) .stream(stream, stream.available(), -1) .contentType(file.getContentType()) .build(); minioClient.putObject(putObjectArgs); stream.close(); if (!minioUrl.endsWith("/")) { minioUrl = minioUrl.concat("/"); } if (!newBucket.endsWith("/")) { newBucket = newBucket.concat("/"); } if (newBucket.startsWith("/")) { newBucket = newBucket.substring(1); } file_url = minioUrl + newBucket + objectName; return file_url; } /** * 上传文件流到minio * * @param stream 文件流 * @param relativePath (带文件名的路径) * @param customBucket 桶名 * @return 文件全路径 */ public static String uploadByInputStream(InputStream stream, String relativePath, String customBucket) throws Exception { String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } initMinio(minioUrl, minioName, minioPass); BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(newBucket).build(); if (minioClient.bucketExists(bucketExistsArgs)) { log.info("Bucket already exists."); } else { // 创建一个名为ota的存储桶 MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(newBucket).build(); minioClient.makeBucket(makeBucketArgs); log.info("create a new bucket as 【" + newBucket + "】!"); } PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(newBucket) .object(relativePath) .stream(stream, stream.available(), -1) .contentType("application/octet-stream") .build(); minioClient.putObject(putObjectArgs); stream.close(); return minioUrl + newBucket + "/" + relativePath; } /** * 上传文件流到minio * * @param stream 文件流 * @param relativePath (带文件名的路径) * @return 文件全路径 */ public static String uploadByInputStream(InputStream stream, String relativePath) throws Exception { return uploadByInputStream(stream, relativePath, bucketName); } /** * 文件上传 * * @param file 文件 * @param bizPath 上传路径 * @return 文件全路径 */ public static String upload(MultipartFile file, String bizPath) throws Exception { return upload(file, bizPath, null, null); } /** * 文件上传 * * @param file 文件 * @param bizPath 上传路径 * @param fileName 文件名称 * @return 文件全路径 */ public static String upload(MultipartFile file, String bizPath, String fileName) throws Exception { return upload(file, bizPath, fileName, null); } /** * 获取文件流 * * @param customBucket 桶名 * @param fileName 文件名(相对路径) * @param isRelative 是否相对路径 * @return */ public static InputStream getMinioFile(String customBucket, String fileName, boolean isRelative) { InputStream inputStream = null; try { initMinio(minioUrl, minioName, minioPass); String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } if (!isRelative) { fileName = fileName.replace(minioUrl, ""); fileName = fileName.replace(newBucket, ""); } GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(newBucket).object(fileName).build(); inputStream = minioClient.getObject(getObjectArgs); } catch (Exception e) { log.error("文件获取失败" + e.getMessage()); } return inputStream; } /** * 获取文件流 * * @param fileName 文件路径 * @param isRelative 是否相对路径 * @return */ public static InputStream getMinioFile(String fileName, boolean isRelative) { return getMinioFile(bucketName, fileName, isRelative); } /** * 删除文件 * * @param customBucket 桶名 * @param fileName 文件名(相对路径) * @param isRelative 是否相对路径 * @throws Exception */ public static void removeObject(String customBucket, String fileName, boolean isRelative) { try { initMinio(minioUrl, minioName, minioPass); String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } if (!isRelative) { if (!minioUrl.endsWith("/")) { minioUrl = minioUrl.concat("/"); } if (newBucket.startsWith("/")) { newBucket = newBucket.substring(1); } fileName = fileName.replace(minioUrl + newBucket, ""); } RemoveObjectArgs removeObjectsArgs = RemoveObjectArgs.builder() .bucket(bucketName) .object(fileName) .build(); minioClient.removeObject(removeObjectsArgs); } catch (Exception e) { log.error("文件删除失败" + e.getMessage()); } } /** * 删除文件 * * @param fileName 文件名(相对路径) * @param isRelative 是否相对路径 * @throws Exception */ public static void removeObject(String fileName, boolean isRelative) { removeObject(bucketName, fileName, isRelative); } /** * 获取文件流 * * @param customBucket 桶名 * @param fileName 文件名(相对路径) * @param out * @param isRelative 是否相对路径 * @return */ public static boolean downFile(String customBucket, String fileName, OutputStream out, boolean isRelative) { InputStream inputStream = null; try { initMinio(minioUrl, minioName, minioPass); String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } if (!isRelative) { fileName = fileName.replace(minioUrl, ""); fileName = fileName.replace(newBucket, ""); } GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(newBucket).object(fileName).build(); inputStream = minioClient.getObject(getObjectArgs); byte[] b = new byte[1024]; int len; while ((len = inputStream.read(b)) != -1) { out.write(b, 0, len); } out.close(); inputStream.close(); } catch (Exception e) { log.error("文件获取失败" + e.getMessage()); return false; } return true; } /** * 获取免签下载地址 * * @param filePath * @return */ public static String getPresignedObjectUrl2upload(String filePath) { String objectUrl = null; initMinio(minioUrl, minioName, minioPass); //有效期600秒 10分钟 GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(filePath) .expiry(600) .build(); try { objectUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs); } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } return objectUrl; } /** * 获取文件流 * * @param customBucket 桶名 * @param fileName 文件名(相对路径) * @param isRelative 是否相对路径 * @return */ public static boolean checkFile(String customBucket, String fileName, boolean isRelative) { InputStream inputStream = null; try { initMinio(minioUrl, minioName, minioPass); String newBucket = bucketName; if (StringUtil.isNotEmpty(customBucket)) { newBucket = customBucket; } if (!isRelative) { fileName = fileName.replace(minioUrl, ""); fileName = fileName.replace(newBucket, ""); } GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(newBucket).object(fileName).build(); inputStream = minioClient.getObject(getObjectArgs); int byteCount = 0; byte[] b = new byte[1024]; int len; while ((len = inputStream.read(b)) != -1) { byteCount += byteCount; } inputStream.close(); if (byteCount > 0) { return true; } else { return false; } } catch (Exception e) { e.printStackTrace(); log.info("文件获取失败" + e.getMessage()); return false; } } /** * 初始化客户端 * * @param minioUrl * @param minioName * @param minioPass * @return */ private static MinioClient initMinio(String minioUrl, String minioName, String minioPass) { if (minioClient == null) { minioClient = MinioClient.builder().endpoint(minioUrl).credentials(minioName, minioPass).build(); } return minioClient; } }