lifuquan vor 1 Jahr
Commit
1e13ea9b7b

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+**/target

+ 1 - 0
README.md

@@ -0,0 +1 @@
+# minio-client-starter

+ 209 - 0
doc/MinioDao.java

@@ -0,0 +1,209 @@
+package top.lifuquan.dao;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.web.multipart.MultipartFile;
+
+import io.minio.BucketExistsArgs;
+import io.minio.GetPresignedObjectUrlArgs;
+import io.minio.ListObjectsArgs;
+import io.minio.MakeBucketArgs;
+import io.minio.MinioClient;
+import io.minio.PutObjectArgs;
+import io.minio.Result;
+import io.minio.http.Method;
+import io.minio.messages.Bucket;
+import io.minio.messages.Item;
+import lombok.extern.slf4j.Slf4j;
+import top.lifuquan.exception.minio.MinioClientGetFailed;
+import top.lifuquan.exception.minio.MinioClientPutFailed;
+
+@Slf4j
+@Repository
+public class MinioDao {
+    
+    private final MinioClient minioClient;
+
+    public MinioDao(MinioClient minioClient) {
+        this.minioClient = minioClient;
+        log.info("已完成{}装配", this.getClass().getName());
+    }
+
+    /*
+     * 获取文件名列表
+     */
+    public List<String> listFileNames(String bucketName) throws MinioClientGetFailed {
+        return listFileNames(bucketName, null);
+    }
+
+    /*
+     * 获取文件名列表
+     */
+    public List<String> listFileNames(String bucketName, String prefix) throws MinioClientGetFailed {
+        Iterable<Result<Item>> results = minioClient
+                .listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).build());
+        List<String> result = new ArrayList<>();
+        try {
+            for (Result<Item> item : results) {
+                result.add(item.get().objectName());
+            }
+        } catch (Exception e) {
+            // result.get() 异常
+            e.printStackTrace();
+            throw new MinioClientGetFailed("通过bucket名称 {} 获取内部元素列表失败", bucketName);
+        }
+        return result;
+    }
+
+    /*
+     * 通过bucket名称打印元素列表
+     */
+    public void printItemsByBucketName(String bucketName) throws MinioClientGetFailed {
+        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
+        Item item;
+        try {
+            for (Result<Item> result : results) {
+                item = result.get();
+                // 路径有很多属性是null
+                if (item.isDir()) {
+                    log.info("路径--属性打印--------  objectName: {}--  size:{}--  owner:{}--  isLatest:{}--  isDir:{}",
+                            item.objectName(), item.size(), item.owner(), item.isLatest(), item.isDir());
+                } else {
+                    log.info("元素--属性打印--------  objectName: {}--  lastModified:{}--  etag:{}--  size:{}--"
+                            + "  storageClass:{}--  owner:{}--  userMetadata:{}--  isLatest:{}--"
+                            + "  versionId:{}--  isDir:{}--  isDeleteMarker:{}",
+                            item.objectName(),
+                            item.lastModified(),
+                            item.etag(),
+                            item.size(),
+                            item.storageClass(),
+                            item.owner().displayName(),
+                            item.userMetadata(),
+                            item.isLatest(),
+                            item.versionId(),
+                            item.isDir(),
+                            item.isDeleteMarker());
+                }
+            }
+        } catch (Exception e) {
+            // result.get() 异常
+            e.printStackTrace();
+            throw new MinioClientGetFailed("通过bucket名称 {} 获取内部元素列表失败", bucketName);
+        }
+    }
+
+    /*
+     * 获取全部的bucket名称
+     */
+    public List<String> listBucketNames() throws MinioClientGetFailed {
+        try {
+            List<Bucket> buckets = minioClient.listBuckets();
+            List<String> result = new ArrayList<>();
+            for (Bucket bucket : buckets) {
+                result.add(bucket.name());
+            }
+            return result;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new MinioClientGetFailed("获取bucket列表失败");
+        }
+    }
+
+    /*
+     * 上传文件
+     * 自动添加日期,格式20221109/
+     * prefix为null 最终格式 20221109/fileName
+     * prefix为abc 最终格式为 abc/20221109/fileName
+     * minio上传完全相同路径文件会覆盖,在文件名之前加上一个uuid字符串
+     * 返回文件在bucket中的完整路径
+     */
+    public String upload(MultipartFile file, String bucketName, String prefix) {
+        // 在原始文件基础上添加日期和前缀
+        String filePath;
+        DateFormat format = new SimpleDateFormat("yyyyMMdd/");
+        String uuid = UUID.randomUUID().toString().replace("-", "");
+        if (prefix != null) {
+            prefix = prefix.endsWith("/") ? prefix : prefix + "/";
+            filePath = prefix + format.format(System.currentTimeMillis()) + uuid + "-" + file.getOriginalFilename();
+        } else {
+            filePath = format.format(System.currentTimeMillis()) + uuid + "-" + file.getOriginalFilename();
+        }
+        PutObjectArgs args;
+        try {
+            args = PutObjectArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(filePath)
+                    .stream(file.getInputStream(), file.getSize(), -1)
+                    .contentType(file.getContentType())
+                    .build();
+            minioClient.putObject(args);
+            return filePath;
+        } catch (Exception e) {
+            // file.getInputStream() 异常 IOException
+            // minioClient.putObject(args) 异常 一大堆
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /*
+     * 获取download链接,默认7天有效
+     */
+    public String download(String bucketName, String filePath) {
+        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs
+                .builder()
+                .method(Method.GET)
+                .bucket(bucketName)
+                .object(filePath)
+                .expiry(7, TimeUnit.DAYS)
+                .build();
+        try {
+            return minioClient.getPresignedObjectUrl(args);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /*
+     * 检查bucket是否存在
+     */
+    public boolean bucketExists(String bucketName) throws Exception {
+        try {
+            return minioClient.bucketExists(BucketExistsArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .build());
+        } catch (IllegalArgumentException e) {
+            throw new MinioClientGetFailed("输入的bucketName--{}--不符合Amazon S3规范: {}", bucketName, e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new MinioClientGetFailed("查询BucketExists出错--{}--{}", bucketName, e.getMessage());
+        }
+    }
+
+    /*
+     * 创建bucket
+     */
+    public void makeBucket(String bucketName) throws Exception {
+        try {
+            minioClient.makeBucket(MakeBucketArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .build());
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+            throw new MinioClientPutFailed("输入的bucketName--{}--不符合Amazon S3规范: {}", bucketName, e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new MinioClientPutFailed("Bucket--{}--创建失败", bucketName);
+        }
+    }
+}

+ 113 - 0
doc/MinioServiceImpl.java

@@ -0,0 +1,113 @@
+package com.nokia.service.file;
+
+import com.nokia.common.exception.MyRuntimeException;
+import com.nokia.config.MinioConfig;
+import io.minio.GetPresignedObjectUrlArgs;
+import io.minio.MinioClient;
+import io.minio.ObjectWriteResponse;
+import io.minio.PutObjectArgs;
+import io.minio.errors.*;
+import io.minio.http.Method;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Primary
+@Slf4j
+@Service
+public class MinioServiceImpl implements FileService {
+
+    private final MinioClient minioClient;
+    private final MinioConfig minioConfig;
+
+    public MinioServiceImpl(MinioClient minioClient, MinioConfig minioConfig) {
+        this.minioClient = minioClient;
+        this.minioConfig = minioConfig;
+    }
+
+    /**
+     * 获取下载地址
+     *
+     * @param object 对象名称
+     * @return {@link String}
+     */
+    @Override
+    public String getDownloadUrl(String object) {
+        return getDownloadUrl(object, minioConfig.getExpiry(), TimeUnit.MINUTES);
+    }
+
+    /**
+     * 获取下载地址
+     *
+     * @param object   对象名称
+     * @param duration 过期时间
+     * @param unit     单位
+     * @return {@link String}
+     */
+    @Override
+    public String getDownloadUrl(String object, int duration, TimeUnit unit) {
+        try {
+            return StringUtils.delete(minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
+                    .expiry(duration, unit)
+                    .bucket(minioConfig.getBucket())
+                    .object(object)
+                    .method(Method.GET)
+                    .build()), minioConfig.getEndpoint());
+        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException |
+                 InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException |
+                 ServerException e) {
+            throw new MyRuntimeException(e);
+        }
+    }
+
+    /**
+     * 从流中上传数据到对象
+     *
+     * @param object     对象名称
+     * @param stream     流
+     * @param objectSize 对象大小
+     * @return {@link Map}<{@link String}, {@link Object}>
+     */
+    @Override
+    public Map<String, Object> putObject(String object, InputStream stream, long objectSize, Map<String, String> tags) {
+        try {
+            ObjectWriteResponse response = minioClient.putObject(PutObjectArgs.builder()
+                    .bucket(minioConfig.getBucket())
+                    .object(object)
+                    .stream(stream, objectSize, -1)
+                    .tags(tags)
+                    .build());
+            Map<String, Object> map = new HashMap<>();
+            map.put("object", response.object());
+            map.put("bucket", response.bucket());
+            map.put("etag", response.etag());
+            map.put("versionId", response.versionId());
+            map.put("headers", response.headers());
+            map.put("region", response.region());
+            return map;
+        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException |
+                 InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |
+                 XmlParserException e) {
+            throw new MyRuntimeException(e);
+        }
+    }
+
+    /**
+     * 获取存储桶名称
+     *
+     * @return {@link String}
+     */
+    @Override
+    public String getBucket() {
+        return minioConfig.getBucket();
+    }
+}

+ 85 - 0
pom.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-parent</artifactId>
+        <version>2.6.14</version>
+        <relativePath />
+    </parent>
+
+    <groupId>com.nokia</groupId>
+    <artifactId>minio-client-starter</artifactId>
+    <version>1.0.snapshot</version>
+
+    <packaging>jar</packaging>
+
+    <properties>
+        <!-- 跳过测试代码 -->
+        <skipTests>true</skipTests>
+        <!-- 指定java的版本 -->
+        <java.version>1.8</java.version>
+        <!-- 文件拷贝时的编码 -->
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <!-- 指定maven-compiler-plugin的配置属性开始 -->
+        <!-- 编译时的编码 -->
+        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
+        <!-- 指定编译的版本 -->
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
+        <!-- 指定maven-compiler-plugin的配置属性结束 -->
+    </properties>
+
+    <dependencies>
+        <!-- minio -->
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>8.5.2</version>
+        </dependency>
+        <!-- spring-boot-starter-web -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!-- spring-boot-autoconfigure -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <!-- spring-boot-configuration-processor -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- spring-boot-starter-test -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!--lombok-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <distributionManagement>
+        <repository>
+            <id>nokia</id>
+            <url>http://nokia.tianhaikj.tk:18081/artifactory/maven-local-releases</url>
+        </repository>
+        <snapshotRepository>
+            <id>nokia</id>
+            <url>http://nokia.tianhaikj.tk:18081/artifactory/maven-local-snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+</project>

+ 14 - 0
src/main/java/com/nokia/minio_client/config/MinioClientAutoConfiguration.java

@@ -0,0 +1,14 @@
+package com.nokia.minio_client.config;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import com.nokia.minio_client.properties.MinioClientProperties;
+
+@Configuration
+@ComponentScan("com.nokia.minio_client")
+@EnableConfigurationProperties(MinioClientProperties.class)
+public class MinioClientAutoConfiguration {
+
+}

+ 14 - 0
src/main/java/com/nokia/minio_client/properties/MinioClientProperties.java

@@ -0,0 +1,14 @@
+package com.nokia.minio_client.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import lombok.Data;
+
+@Data
+@ConfigurationProperties(prefix = "minio.client")
+public class MinioClientProperties {
+
+    private String endpoint;
+    private String access;
+    private String secret;
+}

+ 14 - 0
src/main/java/com/nokia/minio_client/service/MinioClientService.java

@@ -0,0 +1,14 @@
+package com.nokia.minio_client.service;
+
+import org.springframework.stereotype.Service;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+public class MinioClientService {
+
+    public void test() {
+        log.info("====================");
+    }
+}

+ 2 - 0
src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.nokia.minio_client.config.MinioClientAutoConfiguration