package com.zhangmeng.minio.utils; import com.zhangmeng.minio.model.BucketFile; import io.minio.*; import io.minio.errors.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.Item; import javafx.application.Platform; import java.io.*; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author zhangmeng * @version 1.0 * @date 2024-03-07 15:45 */ public class MinioUtils { private static MinioClient minioClient = null; public static Map objectMap = new HashMap<>(); public static String current_bucket = "current_bucket"; public static String primaryStage = "primaryStage"; public static String bucket_choose_action_stage = "bucket_choose_action_stage"; public static String minioController = "minioController"; public static MinioClient getDefault() { if (minioClient == null) { Object endpoint = objectMap.get("endpoint"); Object accessKey = objectMap.get("accessKey"); Object secretKey = objectMap.get("secretKey"); if (endpoint == null ){ Platform.runLater(()->{ AlertUtils.alert_warning("配置文件:endpoint 为空"); }); return null; } if (accessKey == null ){ Platform.runLater(()->{ AlertUtils.alert_warning("配置文件:accessKey 为空"); }); return null; } if (secretKey == null ){ Platform.runLater(()->{ AlertUtils.alert_warning("配置文件:secretKey 为空"); }); return null; } minioClient = MinioClient.builder().endpoint(endpoint.toString()).credentials(accessKey.toString(), secretKey.toString()).build(); } return minioClient; } /** * 获得所有Bucket列表 * * @return */ public static List getAllBuckets() { try { return getDefault().listBuckets(); } catch (ErrorResponseException | InsufficientDataException | InvalidKeyException | InternalException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) { // e.printStackTrace(); Platform.runLater(()->{ AlertUtils.alert_warning("获取Bucket列表失败,请核对配置信息"); }); } return null; } /** * 启动SpringBoot容器的时候初始化Bucket * 如果没有Bucket则创建 * * @param bucketName */ public static void createBucket(String bucketName) { if (!bucketExists(bucketName)) { try { getDefault().makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } catch (ErrorResponseException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException | InsufficientDataException e) { e.printStackTrace(); } }else { Platform.runLater(()->{ AlertUtils.alert_warning("bucket_name : "+ bucketName + "已存在"); }); } } /** * 判断Bucket是否存在,true:存在,false:不存在 * * @param bucketName * @return */ public static Boolean bucketExists(String bucketName) { try { return getDefault().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidResponseException | NoSuchAlgorithmException | XmlParserException | ServerException | IOException | InvalidKeyException e) { e.printStackTrace(); } return null; } public String DateFormatString(ZonedDateTime zonedDateTime){ // 创建一个 DateTimeFormatter 对象,用于定义日期和时间的格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 使用 formatter 来格式化 ZonedDateTime 对象 return zonedDateTime.format(formatter); } /** * 根据文件前置查询文件 * * @param bucketName 存储桶 * @param prefix 前缀 * @param recursive 是否使用递归查询 * @return MinioItem 列表 */ public static List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) { List list = new ArrayList<>(); Iterable> objectsIterator = getDefault().listObjects( ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build()); if (objectsIterator != null) { for (Result o : objectsIterator) { Item item = null; try { item = o.get(); } catch (ErrorResponseException | InsufficientDataException | InvalidKeyException | InvalidResponseException | InternalException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) { e.printStackTrace(); } list.add(item); } } return list; } /** * 获得文件外链 * * @param bucketName * @param objectName * @return url */ public static String getPresignedObjectUrl(String bucketName, String objectName) { GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() .bucket(bucketName) .object(objectName) .method(Method.GET).build(); try { return getDefault() .getPresignedObjectUrl(args); } catch (ErrorResponseException | InsufficientDataException | InvalidKeyException | InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException | IOException | InternalException e) { e.printStackTrace(); } return null; } public static List getFileList(String bucketName){ List itemList = getAllObjectsByPrefix(bucketName, null, true); List list = new ArrayList<>(); if (itemList.size() > 0 ){ list = itemList.stream().map(i -> { BucketFile bucketFile = new BucketFile(); bucketFile.setBucketName(bucketName); bucketFile.setDir(i.isDir()); bucketFile.setFileName(i.objectName()); bucketFile.setSize(i.size()); //获取url String presignedObjectUrl = getPresignedObjectUrl(bucketName, i.objectName()); bucketFile.setUrl(presignedObjectUrl); return bucketFile; }).collect(Collectors.toList()); } return list; } public static void upload_file(File file){ //文件名 String fileName = file.getName(); String newFileName = System.currentTimeMillis() + "." + getFileExtension(fileName); String contentType = getContentType(file); String bucketName = objectMap.get(current_bucket).toString(); if (bucketName == null){ AlertUtils.alert_warning("上传的bucket不能为空!"); return; } uploadFile(bucketName, file, newFileName, contentType); } public static String upload_file(File file,String path){ //文件名 String fileName = file.getName(); String newFileName = System.currentTimeMillis() + "." + getFileExtension(fileName); String contentType = getContentType(file); String bucketName = objectMap.get(current_bucket).toString(); if (bucketName == null){ AlertUtils.alert_warning("上传的bucket不能为空!"); return null; } uploadFile(bucketName, file, path + "/" + newFileName, contentType); return path + "/" + newFileName; } public static String getContentType(File file) { String fileName = file.getName(); String extension = getFileExtension(fileName).toLowerCase(); return switch (extension) { case "jpg", "jpeg" -> "image/jpeg"; case "png" -> "image/png"; case "mp4" -> "video/mp4"; case "gif" -> "image/gif"; case "txt" -> "text/plain"; case "pdf" -> "application/pdf"; case "doc" -> "application/msword"; case "docx" -> "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; case "xls" -> "application/vnd.ms-excel"; case "xlsx" -> "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; case "ppt" -> "application/vnd.ms-powerpoint"; case "pptx" -> "application/vnd.openxmlformats-officedocument.presentationml.presentation"; case "zip" -> "application/zip"; case "tar" -> "application/x-tar"; case "json" -> "application/json"; case "html" -> "text/html"; case "css" -> "text/css"; case "js" -> "application/javascript"; case "mp3" -> "audio/mp3"; case "wav" -> "audio/wav"; case "flac" -> "audio/flac"; case "aac" -> "audio/aac"; case "ogg" -> "audio/ogg"; case "avi" -> "video/avi"; case "mov" -> "video/quicktime"; case "wmv" -> "video/x-ms-wmv"; case "mkv" -> "video/x-matroska"; case "flv" -> "video/x-flv"; case "swf" -> "application/x-shockwave-flash"; case "psd" -> "image/vnd.adobe.photoshop"; case "ai" -> "application/postscript"; case "eps" -> "application/postscript"; case "ps" -> "application/postscript"; case "svg" -> "image/svg+xml"; case "tif" -> "image/tiff"; case "tiff" -> "image/tiff"; case "ico" -> "image/x-icon"; case "md" -> "text/markdown"; case "yaml" -> "text/yaml"; case "yml" -> "text/yaml"; case "xml" -> "text/xml"; case "csv" -> "text/csv"; case "tsv" -> "text/tab-separated-values"; case "jsonl" -> "application/json-seq"; case "bin" -> "application/octet-stream"; case "exe" -> "application/octet-stream"; case "dll" -> "application/octet-stream"; case "so" -> "application/octet-stream"; case "class" -> "application/octet-stream"; case "war" -> "application/octet-stream"; case "ear" -> "application/octet-stream"; case "rar" -> "application/octet-stream"; case "gz" -> "application/gzip"; default -> "application/octet-stream"; }; } // 原生 Java 的等价方法 public static String getFileExtension(String fileName) { if (fileName == null) return ""; int lastDotIndex = fileName.lastIndexOf('.'); // 判断没有点,或者点是第一个字符(例如 ".gitignore") if (lastDotIndex == -1 || lastDotIndex == 0) { return fileName; } return fileName.substring(lastDotIndex + 1); } /** * 使用MultipartFile进行文件上传 * * @param bucketName 存储桶 * @param file 文件名 * @param objectName 对象名 * @param contentType 类型 * @return */ public static ObjectWriteResponse uploadFile(String bucketName, File file, String objectName, String contentType) { FileInputStream inputStream = null; try { inputStream = new FileInputStream(file); return minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .contentType(contentType) .stream(inputStream,inputStream.available(), -1) .build()); } catch (IOException | XmlParserException | InternalException | InvalidKeyException | ErrorResponseException | ServerException | InsufficientDataException | InvalidResponseException | NoSuchAlgorithmException e) { e.printStackTrace(); } finally { if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }