From 91f2a84105d8bf39314036e413b30ffeb8c0454b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=8F=E4=BA=AE?= Date: Thu, 1 Aug 2024 11:42:46 +0800 Subject: [PATCH] initial spring-boot 3 supports --- .gitignore | 7 + .../minio-plus-application-mysql/pom.xml | 1 + .../application/common/WebMvcConfig.java | 10 +- .../minio-plus-application-schedule/pom.xml | 1 + .../application/schedule/task/CleanTask.java | 19 +- .../pom.xml | 47 +++-- .../common/LoginUserInterceptor.java | 4 +- .../application/common/WebMvcConfig.java | 9 +- minio-plus-common/pom.xml | 4 + .../common/config/MinioPlusConfig.java | 12 +- .../common/config/MinioPlusProperties.java | 2 + .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 + minio-plus-core/pom.xml | 6 + .../engine/impl/StorageEngineServiceImpl.java | 21 +- .../core/service/impl/StorageServiceImpl.java | 72 +++---- .../main/resources/META-INF/spring.factories | 3 - ...ot.autoconfigure.AutoConfiguration.imports | 2 + minio-plus-extension/pom.xml | 10 +- .../extension/controller/StorageWebAPI.java | 111 ++++++++++ minio-plus-s3-api/s3-api-minio/pom.xml | 7 + .../s3/official/MinioS3ClientImpl.java | 54 ++--- .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../pom.xml | 3 +- .../controller/StorageController.java | 103 +++++----- .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../pom.xml | 12 +- .../controller/StorageController.java | 191 ++++++++++++++++++ .../pom.xml | 2 + .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 + pom.xml | 49 +++-- 34 files changed, 569 insertions(+), 205 deletions(-) delete mode 100644 minio-plus-common/src/main/resources/META-INF/spring.factories create mode 100644 minio-plus-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 minio-plus-core/src/main/resources/META-INF/spring.factories create mode 100644 minio-plus-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageWebAPI.java delete mode 100644 minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring.factories create mode 100644 minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename {minio-plus-extension => minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter}/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java (65%) delete mode 100644 minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java delete mode 100644 minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/.gitignore b/.gitignore index b922835..44a6a96 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,10 @@ buildNumber.properties # JDT-specific (Eclipse Java Development Tools) .classpath /docs/.vitepress/cache/ + +# IDEA +.idea/ + +# logs +**/logs +**/*.log \ No newline at end of file diff --git a/minio-plus-application/minio-plus-application-mysql/pom.xml b/minio-plus-application/minio-plus-application-mysql/pom.xml index 72de860..92b05cc 100644 --- a/minio-plus-application/minio-plus-application-mysql/pom.xml +++ b/minio-plus-application/minio-plus-application-mysql/pom.xml @@ -34,6 +34,7 @@ org.springframework.boot spring-boot-starter-validation + ${spring-boot.version} com.mysql diff --git a/minio-plus-application/minio-plus-application-mysql/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java b/minio-plus-application/minio-plus-application-mysql/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java index 5994ae6..b238170 100644 --- a/minio-plus-application/minio-plus-application-mysql/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java +++ b/minio-plus-application/minio-plus-application-mysql/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java @@ -4,18 +4,20 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import javax.annotation.Resource; - /** * SpringMVC配置 + * * @author contact@liuxp.me * @since 2024/06/11 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { - @Resource - private LoginUserInterceptor loginUserInterceptor; + private final LoginUserInterceptor loginUserInterceptor; + + public WebMvcConfig(LoginUserInterceptor loginUserInterceptor) { + this.loginUserInterceptor = loginUserInterceptor; + } /** * 前置拦截器 diff --git a/minio-plus-application/minio-plus-application-schedule/pom.xml b/minio-plus-application/minio-plus-application-schedule/pom.xml index 27f34d9..59b55a1 100644 --- a/minio-plus-application/minio-plus-application-schedule/pom.xml +++ b/minio-plus-application/minio-plus-application-schedule/pom.xml @@ -29,6 +29,7 @@ org.springframework.boot spring-boot-starter-validation + ${spring-boot.version} com.mysql diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java index d969b60..8522502 100644 --- a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java +++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java @@ -7,11 +7,11 @@ import org.liuxp.minioplus.api.model.vo.FileMetadataInfoVo; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import javax.annotation.Resource; import java.util.List; /** * 定时任务,演示工程定期清理文件 + * * @author contact@liuxp.me * @since 2024/06/17 */ @@ -19,20 +19,23 @@ import java.util.List; @Slf4j public class CleanTask { - @Resource - private StorageService storageService; + private final StorageService storageService; + + public CleanTask(StorageService storageService) { + this.storageService = storageService; + } @Scheduled(cron = "0 0 */1 * * ?") - public void clean(){ + public void clean() { List fileList = storageService.list(new FileMetadataInfoDTO()); for (FileMetadataInfoVo infoVo : fileList) { - log.info("文件清理,文件key="+infoVo.getFileKey()); - try{ + log.info("文件清理,文件key=" + infoVo.getFileKey()); + try { storageService.remove(infoVo.getFileKey()); - }catch (Exception e){ - log.error(infoVo.getFileKey()+"文件清理失败",e); + } catch (Exception e) { + log.error(infoVo.getFileKey() + "文件清理失败", e); } } } diff --git a/minio-plus-application/minio-plus-application-springboot3/pom.xml b/minio-plus-application/minio-plus-application-springboot3/pom.xml index 029a1fe..2f59614 100644 --- a/minio-plus-application/minio-plus-application-springboot3/pom.xml +++ b/minio-plus-application/minio-plus-application-springboot3/pom.xml @@ -16,23 +16,12 @@ 17 17 UTF-8 - 3.3.2 me.liuxp minio-plus-all-springboot3-starter - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter - - me.liuxp @@ -46,35 +35,45 @@ com.baomidou - mybatis-plus-boot-starter - - - org.springframework.boot - spring-boot-starter - ${springboot3.version} - - - org.springframework.boot - spring-boot-starter-web - ${springboot3.version} + mybatis-plus-spring-boot3-starter + ${mybatisplus.version} org.springframework.boot spring-boot-starter-validation - ${springboot3.version} + ${spring-boot3.version} + + + + org.springframework.boot + spring-boot-starter-jdbc com.mysql mysql-connector-j + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot3.version} + pom + import + + + + org.springframework.boot spring-boot-maven-plugin - ${springboot3.version} + ${spring-boot3.version} diff --git a/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/LoginUserInterceptor.java b/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/LoginUserInterceptor.java index 9a8ccd2..3990c16 100644 --- a/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/LoginUserInterceptor.java +++ b/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/LoginUserInterceptor.java @@ -8,8 +8,8 @@ import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.annotation.Nonnull; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * 登录用户拦截器 diff --git a/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java b/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java index 5994ae6..fe56ab6 100644 --- a/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java +++ b/minio-plus-application/minio-plus-application-springboot3/src/main/java/org/liuxp/minioplus/application/common/WebMvcConfig.java @@ -4,18 +4,21 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import javax.annotation.Resource; /** * SpringMVC配置 + * * @author contact@liuxp.me * @since 2024/06/11 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { - @Resource - private LoginUserInterceptor loginUserInterceptor; + private final LoginUserInterceptor loginUserInterceptor; + + public WebMvcConfig(LoginUserInterceptor loginUserInterceptor) { + this.loginUserInterceptor = loginUserInterceptor; + } /** * 前置拦截器 diff --git a/minio-plus-common/pom.xml b/minio-plus-common/pom.xml index 5b641fb..bf9fdf5 100644 --- a/minio-plus-common/pom.xml +++ b/minio-plus-common/pom.xml @@ -24,11 +24,15 @@ org.springframework.boot spring-boot-starter + ${spring-boot.version} + provided org.springframework.boot spring-boot-configuration-processor + ${spring-boot.version} + provided true diff --git a/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusConfig.java b/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusConfig.java index a587089..c0c3119 100644 --- a/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusConfig.java +++ b/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusConfig.java @@ -1,16 +1,10 @@ package org.liuxp.minioplus.common.config; -import org.springframework.context.annotation.Bean; - /** - * MinioPlusProperties自动配置类 + * MinioPlus自动配置类 + * * @author contact@liuxp.me */ public class MinioPlusConfig { - - @Bean - public MinioPlusProperties tosProperties() { - return new MinioPlusProperties(); - } - + // do noting cuz use components scan } \ No newline at end of file diff --git a/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusProperties.java b/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusProperties.java index b981af8..426eb90 100644 --- a/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusProperties.java +++ b/minio-plus-common/src/main/java/org/liuxp/minioplus/common/config/MinioPlusProperties.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; /** * MinioPlus配置类 @@ -14,6 +15,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; */ @Getter @Setter +@Configuration @ConfigurationProperties(prefix = "minioplus") public class MinioPlusProperties { diff --git a/minio-plus-common/src/main/resources/META-INF/spring.factories b/minio-plus-common/src/main/resources/META-INF/spring.factories deleted file mode 100644 index b5276bd..0000000 --- a/minio-plus-common/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.liuxp.minioplus.common.config.MinioPlusConfig \ No newline at end of file diff --git a/minio-plus-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/minio-plus-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..3951058 --- /dev/null +++ b/minio-plus-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.liuxp.minioplus.common.config.MinioPlusConfig \ No newline at end of file diff --git a/minio-plus-core/pom.xml b/minio-plus-core/pom.xml index fc51ec1..8d7cb86 100644 --- a/minio-plus-core/pom.xml +++ b/minio-plus-core/pom.xml @@ -19,6 +19,12 @@ + + org.springframework.boot + spring-boot-starter + ${spring-boot.version} + provided + me.liuxp minio-plus-common diff --git a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/engine/impl/StorageEngineServiceImpl.java b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/engine/impl/StorageEngineServiceImpl.java index 129840c..6822347 100644 --- a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/engine/impl/StorageEngineServiceImpl.java +++ b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/engine/impl/StorageEngineServiceImpl.java @@ -26,7 +26,6 @@ import org.liuxp.minioplus.s3.def.ListParts; import org.liuxp.minioplus.s3.def.MinioS3Client; import org.springframework.stereotype.Service; -import javax.annotation.Resource; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; @@ -44,14 +43,17 @@ import java.util.Optional; @Slf4j public class StorageEngineServiceImpl implements StorageEngineService { - @Resource - MetadataRepository metadataRepository; + private final MetadataRepository metadataRepository; - @Resource - MinioPlusProperties properties; + private final MinioPlusProperties properties; - @Resource - MinioS3Client minioS3Client; + private final MinioS3Client minioS3Client; + + public StorageEngineServiceImpl(MetadataRepository metadataRepository, MinioPlusProperties properties, MinioS3Client minioS3Client) { + this.metadataRepository = metadataRepository; + this.properties = properties; + this.minioS3Client = minioS3Client; + } /** * 上传任务初始化 @@ -365,7 +367,7 @@ public class StorageEngineServiceImpl implements StorageEngineService { // 文件权限校验,元数据为空或者当前登录用户不是文件所有者时抛出异常 this.authentication(metadata, fileKey, userId); - if(!StorageBucketEnums.IMAGE.getCode().equals(metadata.getStorageBucket())){ + if (!StorageBucketEnums.IMAGE.getCode().equals(metadata.getStorageBucket())) { // 不是图片时,返回文件类型 return metadata.getFileSuffix(); } @@ -413,7 +415,7 @@ public class StorageEngineServiceImpl implements StorageEngineService { @Override public Boolean createFile(FileMetadataInfoSaveDTO saveDTO, byte[] fileBytes) { // 写入文件 - return createFile(saveDTO,new ByteArrayInputStream(fileBytes)); + return createFile(saveDTO, new ByteArrayInputStream(fileBytes)); } @Override @@ -538,6 +540,7 @@ public class StorageEngineServiceImpl implements StorageEngineService { * @param fileSize 文件大小 * @return {@link Integer} */ + @Override public Integer computeChunkNum(Long fileSize) { // 计算分块数量 double tempNum = (double) fileSize / properties.getPart().getSize(); diff --git a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/service/impl/StorageServiceImpl.java b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/service/impl/StorageServiceImpl.java index 3966ed1..d005196 100644 --- a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/service/impl/StorageServiceImpl.java +++ b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/service/impl/StorageServiceImpl.java @@ -26,15 +26,15 @@ import org.liuxp.minioplus.core.engine.StorageEngineService; import org.liuxp.minioplus.core.repository.MetadataRepository; import org.springframework.stereotype.Service; -import javax.annotation.Resource; import java.io.InputStream; import java.util.ArrayList; import java.util.List; /** * 存储组件Service层公共方法实现类 + * * @author contact@liuxp.me - * @since 2023/06/26 + * @since 2023/06/26 */ @Service public class StorageServiceImpl implements StorageService { @@ -42,20 +42,23 @@ public class StorageServiceImpl implements StorageService { /** * 存储引擎Service接口定义 */ - @Resource - StorageEngineService storageEngineService; + private final StorageEngineService storageEngineService; /** * 文件元数据服务接口定义 */ - @Resource - MetadataRepository fileMetadataRepository; + private final MetadataRepository fileMetadataRepository; /** * MinioPlus配置信息注入类 */ - @Resource - MinioPlusProperties properties; + private final MinioPlusProperties properties; + + public StorageServiceImpl(StorageEngineService storageEngineService, MetadataRepository fileMetadataRepository, MinioPlusProperties properties) { + this.storageEngineService = storageEngineService; + this.fileMetadataRepository = fileMetadataRepository; + this.properties = properties; + } @Override public FilePreShardingVo sharding(long fileSize) { @@ -94,11 +97,11 @@ public class StorageServiceImpl implements StorageService { public FileCheckResultVo init(String fileMd5, String fullFileName, long fileSize, Boolean isPrivate, String userId) { // isPrivate 为空时,设置为 false - isPrivate = isPrivate!=null && isPrivate ; + isPrivate = isPrivate != null && isPrivate; - FileCheckResultVo resultVo = storageEngineService.init(fileMd5,fullFileName,fileSize,isPrivate,userId); + FileCheckResultVo resultVo = storageEngineService.init(fileMd5, fullFileName, fileSize, isPrivate, userId); - if(resultVo!=null){ + if (resultVo != null) { for (FileCheckResultVo.Part part : resultVo.getPartList()) { part.setUrl(remakeUrl(part.getUrl())); } @@ -109,9 +112,9 @@ public class StorageServiceImpl implements StorageService { @Override public CompleteResultVo complete(String fileKey, List partMd5List, String userId) { - CompleteResultVo completeResultVo = storageEngineService.complete(fileKey,partMd5List,userId); + CompleteResultVo completeResultVo = storageEngineService.complete(fileKey, partMd5List, userId); - if(completeResultVo!=null){ + if (completeResultVo != null) { for (FileCheckResultVo.Part part : completeResultVo.getPartList()) { part.setUrl(remakeUrl(part.getUrl())); } @@ -122,17 +125,17 @@ public class StorageServiceImpl implements StorageService { @Override public String download(String fileKey, String userId) { - return storageEngineService.download(fileKey,userId); + return storageEngineService.download(fileKey, userId); } @Override public String image(String fileKey, String userId) { - return storageEngineService.image(fileKey,userId); + return storageEngineService.image(fileKey, userId); } @Override public String preview(String fileKey, String userId) { - return storageEngineService.preview(fileKey,userId); + return storageEngineService.preview(fileKey, userId); } @Override @@ -154,7 +157,7 @@ public class StorageServiceImpl implements StorageService { public FileMetadataInfoVo createFile(String fullFileName, Boolean isPrivate, String userId, byte[] fileBytes) { // 组装文件保存入参 - FileMetadataInfoSaveDTO saveDTO = buildSaveDto(fullFileName, isPrivate, userId,fileBytes); + FileMetadataInfoSaveDTO saveDTO = buildSaveDto(fullFileName, isPrivate, userId, fileBytes); // 查询MinIO中是否存在相同MD5值的文件 FileMetadataInfoDTO fileMetadataInfo = new FileMetadataInfoDTO(); @@ -163,9 +166,9 @@ public class StorageServiceImpl implements StorageService { boolean sameMd5 = false; - if(CollUtil.isNotEmpty(alreadyFileList)){ + if (CollUtil.isNotEmpty(alreadyFileList)) { for (FileMetadataInfoVo fileMetadataInfoVo : alreadyFileList) { - if(Boolean.TRUE.equals(fileMetadataInfoVo.getIsFinished())){ + if (Boolean.TRUE.equals(fileMetadataInfoVo.getIsFinished())) { saveDTO.setStorageBucket(fileMetadataInfoVo.getStorageBucket()); saveDTO.setStoragePath(fileMetadataInfoVo.getStoragePath()); sameMd5 = true; @@ -174,7 +177,7 @@ public class StorageServiceImpl implements StorageService { } } - if(!sameMd5){ + if (!sameMd5) { // 新文件时,执行写入逻辑 storageEngineService.createFile(saveDTO, fileBytes); } @@ -185,7 +188,7 @@ public class StorageServiceImpl implements StorageService { @Override public FileMetadataInfoVo createFile(String fullFileName, Boolean isPrivate, String userId, InputStream inputStream) { - return createFile(fullFileName, isPrivate, userId,IoUtil.readBytes(inputStream)); + return createFile(fullFileName, isPrivate, userId, IoUtil.readBytes(inputStream)); } @Override @@ -195,13 +198,13 @@ public class StorageServiceImpl implements StorageService { // 获得输入流 InputStream inputStream = httpResponse.bodyStream(); // 调用处理函数 - return createFile(fullFileName, isPrivate, userId,inputStream); + return createFile(fullFileName, isPrivate, userId, inputStream); } @Override - public FileMetadataInfoVo createBigFile(String fullFileName, String md5, long fileSize,Boolean isPrivate, String userId,InputStream inputStream) { + public FileMetadataInfoVo createBigFile(String fullFileName, String md5, long fileSize, Boolean isPrivate, String userId, InputStream inputStream) { // 组装文件保存入参 - FileMetadataInfoSaveDTO saveDTO = buildSaveDto(fullFileName,md5,fileSize, isPrivate, userId); + FileMetadataInfoSaveDTO saveDTO = buildSaveDto(fullFileName, md5, fileSize, isPrivate, userId); // 查询MinIO中是否存在相同MD5值的文件 FileMetadataInfoDTO fileMetadataInfo = new FileMetadataInfoDTO(); @@ -210,9 +213,9 @@ public class StorageServiceImpl implements StorageService { boolean sameMd5 = false; - if(CollUtil.isNotEmpty(alreadyFileList)){ + if (CollUtil.isNotEmpty(alreadyFileList)) { for (FileMetadataInfoVo fileMetadataInfoVo : alreadyFileList) { - if(Boolean.TRUE.equals(fileMetadataInfoVo.getIsFinished())){ + if (Boolean.TRUE.equals(fileMetadataInfoVo.getIsFinished())) { saveDTO.setStorageBucket(fileMetadataInfoVo.getStorageBucket()); saveDTO.setStoragePath(fileMetadataInfoVo.getStoragePath()); sameMd5 = true; @@ -221,7 +224,7 @@ public class StorageServiceImpl implements StorageService { } } - if(!sameMd5){ + if (!sameMd5) { // 新文件时,执行写入逻辑 storageEngineService.createFile(saveDTO, inputStream); } @@ -230,7 +233,7 @@ public class StorageServiceImpl implements StorageService { } @Override - public Pair read(String fileKey) { + public Pair read(String fileKey) { return storageEngineService.read(fileKey); } @@ -239,18 +242,18 @@ public class StorageServiceImpl implements StorageService { return storageEngineService.remove(fileKey); } - FileMetadataInfoSaveDTO buildSaveDto(String fullFileName, Boolean isPrivate, String userId, byte[] fileBytes){ + FileMetadataInfoSaveDTO buildSaveDto(String fullFileName, Boolean isPrivate, String userId, byte[] fileBytes) { - if(null==fileBytes){ + if (null == fileBytes) { throw new MinioPlusException(MinioPlusErrorCode.FILE_BYTES_FAILED); } // 计算文件MD5值 String md5 = SecureUtil.md5().digestHex(fileBytes); - return buildSaveDto(fullFileName,md5,fileBytes.length,isPrivate,userId); + return buildSaveDto(fullFileName, md5, fileBytes.length, isPrivate, userId); } - FileMetadataInfoSaveDTO buildSaveDto(String fullFileName, String md5,long fileSize,Boolean isPrivate, String userId){ + FileMetadataInfoSaveDTO buildSaveDto(String fullFileName, String md5, long fileSize, Boolean isPrivate, String userId) { // 生成UUID作为文件KEY String key = IdUtil.fastSimpleUUID(); @@ -290,12 +293,13 @@ public class StorageServiceImpl implements StorageService { /** * 重写文件地址 + * * @param url 文件地址 * @return 重写后的文件地址 */ - private String remakeUrl(String url){ + private String remakeUrl(String url) { - if(CharSequenceUtil.isNotBlank(properties.getBrowserUrl())){ + if (CharSequenceUtil.isNotBlank(properties.getBrowserUrl())) { return url.replace(properties.getBackend(), properties.getBrowserUrl()); } return url; diff --git a/minio-plus-core/src/main/resources/META-INF/spring.factories b/minio-plus-core/src/main/resources/META-INF/spring.factories deleted file mode 100644 index a7b1302..0000000 --- a/minio-plus-core/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.liuxp.minioplus.core.service.impl.StorageServiceImpl,\ -org.liuxp.minioplus.core.engine.impl.StorageEngineServiceImpl \ No newline at end of file diff --git a/minio-plus-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/minio-plus-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..c8dbcf0 --- /dev/null +++ b/minio-plus-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +#org.liuxp.minioplus.core.service.impl.StorageServiceImpl +#org.liuxp.minioplus.core.engine.impl.StorageEngineServiceImpl \ No newline at end of file diff --git a/minio-plus-extension/pom.xml b/minio-plus-extension/pom.xml index a0f4180..f0f5006 100644 --- a/minio-plus-extension/pom.xml +++ b/minio-plus-extension/pom.xml @@ -20,7 +20,15 @@ org.springframework.boot spring-boot-starter-web + ${spring-boot.version} + provided + true + - \ No newline at end of file diff --git a/minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageWebAPI.java b/minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageWebAPI.java new file mode 100644 index 0000000..211ef75 --- /dev/null +++ b/minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageWebAPI.java @@ -0,0 +1,111 @@ +package org.liuxp.minioplus.extension.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.liuxp.minioplus.api.model.vo.FileCheckResultVo; +import org.liuxp.minioplus.api.model.vo.FilePreShardingVo; +import org.liuxp.minioplus.extension.context.Response; +import org.liuxp.minioplus.extension.dto.FileCheckDTO; +import org.liuxp.minioplus.extension.dto.FileCompleteDTO; +import org.liuxp.minioplus.extension.dto.PreShardingDTO; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 对象存储标准接口定义 + * 本类的方法是给前端使用的方法 + * + * @author contact@liuxp.me + * @since 2024/6/18 + */ +@Tag(name = "MinIO Plus 接口") +public interface StorageWebAPI { + + /** + * 请求地址前缀 + */ + String ROOT_PATH = "/storage"; + + /** + * 图标请求地址 + */ + String ICON_PATH = "/storage/icon/"; + + /** + * 文件预分片方法 + * 在大文件上传时,为了防止前端重复计算文件MD5值,提供该方法 + * + * @param preShardingDTO 文件预分片入参DTO + * @return 预分片结果 + */ + @Operation(summary = "文件预分片") + @PostMapping("/upload/sharding") + @ResponseBody + Response sharding(@RequestBody @Validated PreShardingDTO preShardingDTO); + + /** + * 上传任务初始化 + * 上传前的预检查:秒传、分块上传和断点续传等特性均基于该方法实现 + * + * @param fileCheckDTO 文件预检查入参 + * @return 检查结果 + */ + @Operation(summary = "上传任务初始化") + @PostMapping("/upload/init") + @ResponseBody + Response init(@RequestBody @Validated FileCheckDTO fileCheckDTO); + + /** + * 文件上传完成 + * + * @param fileKey 文件KEY + * @param fileCompleteDTO 文件完成入参DTO + * @return 是否成功 + */ + @Operation(summary = "上传完成") + @PostMapping("/upload/complete/{fileKey}") + @ResponseBody + Response complete(@PathVariable("fileKey") String fileKey, @RequestBody FileCompleteDTO fileCompleteDTO); + + /** + * 文件下载 + * + * @param fileKey 文件KEY + * @return 文件下载地址 + */ + @Operation(summary = "文件下载") + @GetMapping("/download/{fileKey}") + String download(@PathVariable("fileKey") String fileKey); + + /** + * 获取图像 + * + * @param fileKey 文件KEY + * @return 原图地址 + */ + @Operation(summary = "图片预览 - 原图") + @GetMapping("/image/{fileKey}") + String previewOriginal(@PathVariable("fileKey") String fileKey); + + /** + * 文件预览 + * 当文件为图片时,返回图片的缩略图 + * 当文件不是图片时,返回文件类型图标 + * + * @param fileKey 文件KEY + * @return 缩略图地址 + */ + @Operation(summary = "图片预览 - 缩略图") + @GetMapping("/preview/{fileKey}") + String previewMedium(@PathVariable("fileKey") String fileKey); + + /** + * 根据文件类型取得图标 + * + * @param fileType 文件扩展名 + */ + @Operation(summary = "获取图标") + @GetMapping("/icon/{fileType}") + void icon(@PathVariable("fileType") String fileType); + +} \ No newline at end of file diff --git a/minio-plus-s3-api/s3-api-minio/pom.xml b/minio-plus-s3-api/s3-api-minio/pom.xml index ad6a877..cbe7ad4 100644 --- a/minio-plus-s3-api/s3-api-minio/pom.xml +++ b/minio-plus-s3-api/s3-api-minio/pom.xml @@ -26,6 +26,13 @@ me.liuxp minio-plus-common + + org.slf4j + slf4j-log4j12 + 1.7.36 + provided + true + \ No newline at end of file diff --git a/minio-plus-s3-api/s3-api-minio/src/main/java/org/liuxp/minioplus/s3/official/MinioS3ClientImpl.java b/minio-plus-s3-api/s3-api-minio/src/main/java/org/liuxp/minioplus/s3/official/MinioS3ClientImpl.java index ed68884..e0510ce 100644 --- a/minio-plus-s3-api/s3-api-minio/src/main/java/org/liuxp/minioplus/s3/official/MinioS3ClientImpl.java +++ b/minio-plus-s3-api/s3-api-minio/src/main/java/org/liuxp/minioplus/s3/official/MinioS3ClientImpl.java @@ -9,14 +9,12 @@ import io.minio.errors.XmlParserException; import io.minio.http.Method; import io.minio.messages.Part; import lombok.extern.slf4j.Slf4j; +import org.liuxp.minioplus.common.config.MinioPlusProperties; import org.liuxp.minioplus.common.enums.MinioPlusErrorCode; import org.liuxp.minioplus.common.exception.MinioPlusException; -import org.liuxp.minioplus.common.config.MinioPlusProperties; import org.liuxp.minioplus.s3.def.ListParts; import org.liuxp.minioplus.s3.def.MinioS3Client; -import org.springframework.stereotype.Repository; -import javax.annotation.Resource; import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; @@ -29,7 +27,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @Slf4j -@Repository public class MinioS3ClientImpl implements MinioS3Client { /** @@ -41,14 +38,17 @@ public class MinioS3ClientImpl implements MinioS3Client { */ private static final String PART_NUMBER = "partNumber"; - @Resource - private MinioPlusProperties properties; + private final MinioPlusProperties properties; private CustomMinioClient minioClient = null; - public CustomMinioClient getClient(){ + public MinioS3ClientImpl(MinioPlusProperties properties) { + this.properties = properties; + } - if(null==this.minioClient){ + public CustomMinioClient getClient() { + + if (null == this.minioClient) { MinioAsyncClient client = MinioAsyncClient.builder() .endpoint(properties.getBackend()) .credentials(properties.getKey(), properties.getSecret()) @@ -63,8 +63,9 @@ public class MinioS3ClientImpl implements MinioS3Client { public Boolean bucketExists(String bucketName) { try { return this.getClient().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()).get(); - } catch (InsufficientDataException | InternalException | InvalidKeyException | IOException | NoSuchAlgorithmException | XmlParserException | ExecutionException | InterruptedException e) { - log.error(MinioPlusErrorCode.BUCKET_EXISTS_FAILED.getMessage()+":{}", e.getMessage(), e); + } catch (InsufficientDataException | InternalException | InvalidKeyException | IOException | + NoSuchAlgorithmException | XmlParserException | ExecutionException | InterruptedException e) { + log.error("{}:{}", MinioPlusErrorCode.BUCKET_EXISTS_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.BUCKET_EXISTS_FAILED); } } @@ -78,7 +79,7 @@ public class MinioS3ClientImpl implements MinioS3Client { this.getClient().makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } } catch (Exception e) { - log.error(MinioPlusErrorCode.MAKE_BUCKET_FAILED.getMessage()+":{}", e.getMessage(), e); + log.error("{}:{}", MinioPlusErrorCode.MAKE_BUCKET_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.MAKE_BUCKET_FAILED); } } @@ -89,7 +90,7 @@ public class MinioS3ClientImpl implements MinioS3Client { CreateMultipartUploadResponse createMultipartUploadResponse = this.getClient().createMultipartUpload(bucketName, null, objectName, null, null); return createMultipartUploadResponse.result().uploadId(); } catch (Exception e) { - log.error(MinioPlusErrorCode.CREATE_MULTIPART_UPLOAD_FAILED.getMessage()+":{}", e.getMessage(), e); + log.error("{}:{}", MinioPlusErrorCode.CREATE_MULTIPART_UPLOAD_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.CREATE_MULTIPART_UPLOAD_FAILED); } } @@ -100,7 +101,7 @@ public class MinioS3ClientImpl implements MinioS3Client { Part[] partArray = new Part[parts.size()]; for (int i = 0; i < parts.size(); i++) { - partArray[i] = new Part(parts.get(i).getPartNumber(),parts.get(i).getEtag()); + partArray[i] = new Part(parts.get(i).getPartNumber(), parts.get(i).getEtag()); } try { @@ -108,7 +109,7 @@ public class MinioS3ClientImpl implements MinioS3Client { , objectName, uploadId, partArray, null, null); return objectWriteResponse != null; } catch (Exception e) { - log.error(MinioPlusErrorCode.COMPLETE_MULTIPART_FAILED.getMessage()+",uploadId:{},ObjectName:{},失败原因:{},", uploadId, objectName, e.getMessage(), e); + log.error("{},uploadId:{},ObjectName:{},失败原因:{},", MinioPlusErrorCode.COMPLETE_MULTIPART_FAILED.getMessage(), uploadId, objectName, e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.COMPLETE_MULTIPART_FAILED); } } @@ -134,14 +135,14 @@ public class MinioS3ClientImpl implements MinioS3Client { } catch (Exception e) { // 查询分片失败,打印日志,返回空的分片信息 - log.error(MinioPlusErrorCode.LIST_PARTS_FAILED.getMessage()+":{}", e.getMessage()); + log.error("{}:{}", MinioPlusErrorCode.LIST_PARTS_FAILED.getMessage(), e.getMessage()); } return listParts; } @Override - public String getUploadObjectUrl(String bucketName, String objectName, String uploadId,String partNumber) { + public String getUploadObjectUrl(String bucketName, String objectName, String uploadId, String partNumber) { Map queryParams = Maps.newHashMapWithExpectedSize(2); queryParams.put(UPLOAD_ID, uploadId); @@ -157,7 +158,7 @@ public class MinioS3ClientImpl implements MinioS3Client { .extraQueryParams(queryParams) .build()); } catch (Exception e) { - log.error(MinioPlusErrorCode.CREATE_UPLOAD_URL_FAILED.getMessage()+":{}", e.getMessage(), e); + log.error("{}:{}", MinioPlusErrorCode.CREATE_UPLOAD_URL_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.CREATE_UPLOAD_URL_FAILED); } } @@ -165,7 +166,7 @@ public class MinioS3ClientImpl implements MinioS3Client { @Override public String getDownloadUrl(String fileName, String contentType, String bucketName, String objectName) { Map reqParams = new HashMap<>(); - reqParams.put("response-content-disposition", "attachment;filename=\""+fileName+"\""); + reqParams.put("response-content-disposition", "attachment;filename=\"" + fileName + "\""); reqParams.put("response-content-type", contentType); try { @@ -178,7 +179,7 @@ public class MinioS3ClientImpl implements MinioS3Client { .extraQueryParams(reqParams) .build()); } catch (Exception e) { - log.error(MinioPlusErrorCode.CREATE_DOWNLOAD_URL_FAILED.getMessage()+":{}", e.getMessage(), e); + log.error("{}:{}", MinioPlusErrorCode.CREATE_DOWNLOAD_URL_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.CREATE_DOWNLOAD_URL_FAILED); } } @@ -199,14 +200,14 @@ public class MinioS3ClientImpl implements MinioS3Client { .extraQueryParams(reqParams) .build()); } catch (Exception e) { - log.error(MinioPlusErrorCode.CREATE_PREVIEW_URL_FAILED.getMessage()+":{}", e.getMessage(), e); + log.error("{}:{}", MinioPlusErrorCode.CREATE_PREVIEW_URL_FAILED.getMessage(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.CREATE_PREVIEW_URL_FAILED); } } @Override public Boolean putObject(String bucketName, String objectName, InputStream stream, long size, String contentType) { - try{ + try { // 检查存储桶是否已经存在 boolean isExist = this.getClient().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()).get(); @@ -220,12 +221,13 @@ public class MinioS3ClientImpl implements MinioS3Client { this.getClient().putObject(PutObjectArgs.builder() .bucket(bucketName) .object(objectName) - .stream(stream,size,0L) + .stream(stream, size, 0L) .contentType(contentType) .build()); - } catch (InsufficientDataException | InternalException | InvalidKeyException | IOException | NoSuchAlgorithmException | XmlParserException | ExecutionException | InterruptedException e) { - log.error(MinioPlusErrorCode.WRITE_FAILED.getMessage(),e); + } catch (InsufficientDataException | InternalException | InvalidKeyException | IOException | + NoSuchAlgorithmException | XmlParserException | ExecutionException | InterruptedException e) { + log.error(MinioPlusErrorCode.WRITE_FAILED.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.WRITE_FAILED); } @@ -239,7 +241,7 @@ public class MinioS3ClientImpl implements MinioS3Client { // 文件流转换为字节码 return IoUtil.readBytes(inputStream); } catch (Exception e) { - log.error(MinioPlusErrorCode.READ_FAILED.getMessage(),e); + log.error(MinioPlusErrorCode.READ_FAILED.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.READ_FAILED); } } @@ -249,7 +251,7 @@ public class MinioS3ClientImpl implements MinioS3Client { try { this.getClient().removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); } catch (Exception e) { - log.error(MinioPlusErrorCode.DELETE_FAILED.getMessage(),e); + log.error(MinioPlusErrorCode.DELETE_FAILED.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.DELETE_FAILED); } } diff --git a/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring.factories b/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ed11e3f..0000000 --- a/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.liuxp.minioplus.s3.official.MinioS3ClientImpl \ No newline at end of file diff --git a/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..4c39c6c --- /dev/null +++ b/minio-plus-s3-api/s3-api-minio/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.liuxp.minioplus.s3.official.MinioS3ClientImpl \ No newline at end of file diff --git a/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/pom.xml b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/pom.xml index 852de9e..e3bf42e 100644 --- a/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/pom.xml +++ b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/pom.xml @@ -21,7 +21,8 @@ org.springframework.boot - spring-boot-starter + spring-boot-starter-web + ${spring-boot2.version} me.liuxp diff --git a/minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java similarity index 65% rename from minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java rename to minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java index 30100fb..891c546 100644 --- a/minio-plus-extension/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java +++ b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java @@ -1,8 +1,6 @@ package org.liuxp.minioplus.extension.controller; import cn.hutool.core.io.IoUtil; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.liuxp.minioplus.api.StorageService; import org.liuxp.minioplus.api.model.vo.CompleteResultVo; @@ -20,50 +18,48 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; /** * 对象存储标准接口定义 * 本类的方法是给前端使用的方法 + * * @author contact@liuxp.me * @since 2024/6/18 */ -@Controller -@RequestMapping("/storage") -@Tag(name = "MinIO Plus 接口") @Slf4j -public class StorageController { +@Controller +@RequestMapping(StorageWebAPI.ROOT_PATH) +public class StorageController implements StorageWebAPI { /** * 重定向 */ private static final String REDIRECT_PREFIX = "redirect:"; - /** - * 图标请求地址 - */ - private static final String ICON_PATH = "/storage/icon/"; - /** * 存储引擎Service接口定义 */ - @Resource - private StorageService storageService; + private final StorageService storageService; + + public StorageController(StorageService storageService) { + this.storageService = storageService; + } /** * 文件预分片方法 * 在大文件上传时,为了防止前端重复计算文件MD5值,提供该方法 + * * @param preShardingDTO 文件预分片入参DTO * @return 预分片结果 */ - @Operation(summary = "文件预分片") - @PostMapping("/upload/sharding") - @ResponseBody - public Response sharding(@RequestBody @Validated PreShardingDTO preShardingDTO){ + @Override + public Response sharding(@RequestBody @Validated PreShardingDTO preShardingDTO) { FilePreShardingVo resultVo = storageService.sharding(preShardingDTO.getFileSize()); @@ -73,51 +69,49 @@ public class StorageController { /** * 上传任务初始化 * 上传前的预检查:秒传、分块上传和断点续传等特性均基于该方法实现 + * * @param fileCheckDTO 文件预检查入参 * @return 检查结果 */ - @Operation(summary = "上传任务初始化") - @PostMapping("/upload/init") - @ResponseBody - public Response init(@RequestBody @Validated FileCheckDTO fileCheckDTO) { + @Override + public Response init(FileCheckDTO fileCheckDTO) { // 取得当前登录用户信息 String userId = UserHolder.get(); - FileCheckResultVo resultVo = storageService.init(fileCheckDTO.getFileMd5(),fileCheckDTO.getFullFileName(),fileCheckDTO.getFileSize(),fileCheckDTO.getIsPrivate(),userId); + FileCheckResultVo resultVo = storageService.init(fileCheckDTO.getFileMd5(), fileCheckDTO.getFullFileName(), fileCheckDTO.getFileSize(), fileCheckDTO.getIsPrivate(), userId); return Response.success(resultVo); } /** * 文件上传完成 - * @param fileKey 文件KEY + * + * @param fileKey 文件KEY * @param fileCompleteDTO 文件完成入参DTO * @return 是否成功 */ - @Operation(summary = "上传完成") - @PostMapping("/upload/complete/{fileKey}") - @ResponseBody - public Response complete(@PathVariable("fileKey") String fileKey, @RequestBody FileCompleteDTO fileCompleteDTO) { + @Override + public Response complete(String fileKey, FileCompleteDTO fileCompleteDTO) { // 取得当前登录用户信息 String userId = UserHolder.get(); // 打印调试日志 - log.debug("合并文件开始fileKey="+fileKey+",partMd5List="+fileCompleteDTO.getPartMd5List()); - CompleteResultVo completeResultVo = storageService.complete(fileKey,fileCompleteDTO.getPartMd5List(),userId); + log.debug("合并文件开始fileKey=" + fileKey + ",partMd5List=" + fileCompleteDTO.getPartMd5List()); + CompleteResultVo completeResultVo = storageService.complete(fileKey, fileCompleteDTO.getPartMd5List(), userId); return Response.success(completeResultVo); } /** * 文件下载 + * * @param fileKey 文件KEY * @return 文件下载地址 */ - @Operation(summary = "文件下载") - @GetMapping("/download/{fileKey}") - public String download(@PathVariable String fileKey) { + @Override + public String download(String fileKey) { // 取得当前登录用户信息 String userId = UserHolder.get(); @@ -128,12 +122,12 @@ public class StorageController { /** * 获取图像 + * * @param fileKey 文件KEY * @return 原图地址 */ - @Operation(summary = "图片预览 - 原图") - @GetMapping("/image/{fileKey}") - public String previewOriginal(@PathVariable String fileKey) { + @Override + public String previewOriginal(String fileKey) { // 取得当前登录用户信息 String userId = UserHolder.get(); @@ -146,18 +140,18 @@ public class StorageController { * 文件预览 * 当文件为图片时,返回图片的缩略图 * 当文件不是图片时,返回文件类型图标 + * * @param fileKey 文件KEY * @return 缩略图地址 */ - @Operation(summary = "图片预览 - 缩略图") - @GetMapping("/preview/{fileKey}") - public String previewMedium(@PathVariable String fileKey) { + @Override + public String previewMedium(String fileKey) { // 取得当前登录用户信息 String userId = UserHolder.get(); String url = storageService.preview(fileKey, userId); - if(url.length()<10){ + if (url.length() < 10) { // 当返回值为文件类型时,取得图标 url = ICON_PATH + url; } @@ -168,30 +162,27 @@ public class StorageController { /** * 根据文件类型取得图标 - * @param response HttpServletResponse + * * @param fileType 文件扩展名 */ - @Operation(summary = "获取图标") - @GetMapping("/icon/{fileType}") - public void icon(HttpServletResponse response,@PathVariable String fileType) { + @Override + public void icon(String fileType) { try { - // 根据文件后缀取得桶 String storageBucket = StorageBucketEnums.getBucketByFileSuffix(fileType); - ClassPathResource cpr = new ClassPathResource(storageBucket+".png"); + ClassPathResource cpr = new ClassPathResource(storageBucket + ".png"); byte[] bytes = FileCopyUtils.copyToByteArray(cpr.getInputStream()); - response.setHeader("content-disposition", "inline"); - response.setHeader("Content-Length", String.valueOf(bytes.length)); - ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); - - IoUtil.copy(inputStream, response.getOutputStream()); - inputStream.close(); - + ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + attr.getResponse().setHeader("content-disposition", "inline"); + attr.getResponse().setHeader("Content-Length", String.valueOf(bytes.length)); + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) { + IoUtil.copy(inputStream, attr.getResponse().getOutputStream()); + } } catch (Exception e) { - log.error(MinioPlusErrorCode.FILE_ICON_FAILED.getMessage(),e); + log.error(MinioPlusErrorCode.FILE_ICON_FAILED.getMessage(), e); // 图标获取失败 throw new MinioPlusException(MinioPlusErrorCode.FILE_ICON_FAILED); } diff --git a/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring.factories b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index a149910..0000000 --- a/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - org.liuxp.minioplus.common.config.MinioPlusAutoConfiguration \ No newline at end of file diff --git a/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..a343f0d --- /dev/null +++ b/minio-plus-spring-boot-starter/minio-plus-all-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.liuxp.minioplus.common.config.MinioPlusAutoConfiguration \ No newline at end of file diff --git a/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/pom.xml b/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/pom.xml index 5880df7..ee14199 100644 --- a/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/pom.xml +++ b/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/pom.xml @@ -15,11 +15,21 @@ 17 17 + UTF-8 - + + org.springframework.boot + spring-boot-starter-web + ${spring-boot3.version} + + + jakarta.servlet + jakarta.servlet-api + + me.liuxp minio-plus-extension diff --git a/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java b/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java new file mode 100644 index 0000000..891c546 --- /dev/null +++ b/minio-plus-spring-boot-starter/minio-plus-all-springboot3-starter/src/main/java/org/liuxp/minioplus/extension/controller/StorageController.java @@ -0,0 +1,191 @@ +package org.liuxp.minioplus.extension.controller; + +import cn.hutool.core.io.IoUtil; +import lombok.extern.slf4j.Slf4j; +import org.liuxp.minioplus.api.StorageService; +import org.liuxp.minioplus.api.model.vo.CompleteResultVo; +import org.liuxp.minioplus.api.model.vo.FileCheckResultVo; +import org.liuxp.minioplus.api.model.vo.FilePreShardingVo; +import org.liuxp.minioplus.common.enums.MinioPlusErrorCode; +import org.liuxp.minioplus.common.enums.StorageBucketEnums; +import org.liuxp.minioplus.common.exception.MinioPlusException; +import org.liuxp.minioplus.extension.context.Response; +import org.liuxp.minioplus.extension.context.UserHolder; +import org.liuxp.minioplus.extension.dto.FileCheckDTO; +import org.liuxp.minioplus.extension.dto.FileCompleteDTO; +import org.liuxp.minioplus.extension.dto.PreShardingDTO; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Controller; +import org.springframework.util.FileCopyUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.ByteArrayInputStream; + +/** + * 对象存储标准接口定义 + * 本类的方法是给前端使用的方法 + * + * @author contact@liuxp.me + * @since 2024/6/18 + */ +@Slf4j +@Controller +@RequestMapping(StorageWebAPI.ROOT_PATH) +public class StorageController implements StorageWebAPI { + + /** + * 重定向 + */ + private static final String REDIRECT_PREFIX = "redirect:"; + + /** + * 存储引擎Service接口定义 + */ + private final StorageService storageService; + + public StorageController(StorageService storageService) { + this.storageService = storageService; + } + + /** + * 文件预分片方法 + * 在大文件上传时,为了防止前端重复计算文件MD5值,提供该方法 + * + * @param preShardingDTO 文件预分片入参DTO + * @return 预分片结果 + */ + @Override + public Response sharding(@RequestBody @Validated PreShardingDTO preShardingDTO) { + + FilePreShardingVo resultVo = storageService.sharding(preShardingDTO.getFileSize()); + + return Response.success(resultVo); + } + + /** + * 上传任务初始化 + * 上传前的预检查:秒传、分块上传和断点续传等特性均基于该方法实现 + * + * @param fileCheckDTO 文件预检查入参 + * @return 检查结果 + */ + @Override + public Response init(FileCheckDTO fileCheckDTO) { + + // 取得当前登录用户信息 + String userId = UserHolder.get(); + + FileCheckResultVo resultVo = storageService.init(fileCheckDTO.getFileMd5(), fileCheckDTO.getFullFileName(), fileCheckDTO.getFileSize(), fileCheckDTO.getIsPrivate(), userId); + + return Response.success(resultVo); + } + + /** + * 文件上传完成 + * + * @param fileKey 文件KEY + * @param fileCompleteDTO 文件完成入参DTO + * @return 是否成功 + */ + @Override + public Response complete(String fileKey, FileCompleteDTO fileCompleteDTO) { + + // 取得当前登录用户信息 + String userId = UserHolder.get(); + + // 打印调试日志 + log.debug("合并文件开始fileKey=" + fileKey + ",partMd5List=" + fileCompleteDTO.getPartMd5List()); + CompleteResultVo completeResultVo = storageService.complete(fileKey, fileCompleteDTO.getPartMd5List(), userId); + + return Response.success(completeResultVo); + } + + /** + * 文件下载 + * + * @param fileKey 文件KEY + * @return 文件下载地址 + */ + @Override + public String download(String fileKey) { + + // 取得当前登录用户信息 + String userId = UserHolder.get(); + + // 取得文件读取路径 + return REDIRECT_PREFIX + storageService.download(fileKey, userId); + } + + /** + * 获取图像 + * + * @param fileKey 文件KEY + * @return 原图地址 + */ + @Override + public String previewOriginal(String fileKey) { + + // 取得当前登录用户信息 + String userId = UserHolder.get(); + + // 取得文件读取路径 + return REDIRECT_PREFIX + storageService.image(fileKey, userId); + } + + /** + * 文件预览 + * 当文件为图片时,返回图片的缩略图 + * 当文件不是图片时,返回文件类型图标 + * + * @param fileKey 文件KEY + * @return 缩略图地址 + */ + @Override + public String previewMedium(String fileKey) { + + // 取得当前登录用户信息 + String userId = UserHolder.get(); + + String url = storageService.preview(fileKey, userId); + if (url.length() < 10) { + // 当返回值为文件类型时,取得图标 + url = ICON_PATH + url; + } + + // 取得文件读取路径 + return REDIRECT_PREFIX + url; + } + + /** + * 根据文件类型取得图标 + * + * @param fileType 文件扩展名 + */ + @Override + public void icon(String fileType) { + try { + // 根据文件后缀取得桶 + String storageBucket = StorageBucketEnums.getBucketByFileSuffix(fileType); + + ClassPathResource cpr = new ClassPathResource(storageBucket + ".png"); + + byte[] bytes = FileCopyUtils.copyToByteArray(cpr.getInputStream()); + + ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + attr.getResponse().setHeader("content-disposition", "inline"); + attr.getResponse().setHeader("Content-Length", String.valueOf(bytes.length)); + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) { + IoUtil.copy(inputStream, attr.getResponse().getOutputStream()); + } + } catch (Exception e) { + log.error(MinioPlusErrorCode.FILE_ICON_FAILED.getMessage(), e); + // 图标获取失败 + throw new MinioPlusException(MinioPlusErrorCode.FILE_ICON_FAILED); + } + } + +} \ No newline at end of file diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml index f8240b2..614623f 100644 --- a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml +++ b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml @@ -22,6 +22,8 @@ org.springframework.boot spring-boot-starter + ${spring-boot.version} + provided me.liuxp diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index a149910..0000000 --- a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - org.liuxp.minioplus.common.config.MinioPlusAutoConfiguration \ No newline at end of file diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..a343f0d --- /dev/null +++ b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.liuxp.minioplus.common.config.MinioPlusAutoConfiguration \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8829fea..e979f63 100644 --- a/pom.xml +++ b/pom.xml @@ -50,9 +50,13 @@ 1.8 3.0.1 0.1.5 - 2.7.18 + 2.7.18 + 3.3.2 + ${spring-boot2.version} 3.5.7 + 8.0.33 1.18.32 + 6.0.0 5.8.28 4.4.0 2.2.8 @@ -63,24 +67,44 @@ - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - + com.baomidou mybatis-plus-boot-starter ${mybatisplus.version} + + com.baomidou + mybatis-plus-spring-boot3-starter + ${mybatisplus.version} + + + com.mysql + mysql-connector-j + ${mysql-connector-j.version} + + + + jakarta.servlet + jakarta.servlet-api + ${jakarta-servlet-api.version} + + org.projectlombok lombok ${lombok.version} + cn.hutool hutool-all @@ -103,13 +127,6 @@ swagger-annotations ${swagger.version} - - - com.baomidou - mybatis-plus - ${mybatisplus.version} - compile - io.minio