From 825b1cbf748b022d8497f56fed7eba7026c79acb Mon Sep 17 00:00:00 2001 From: xuchang Date: Wed, 7 Apr 2021 17:57:13 +0800 Subject: [PATCH] =?UTF-8?q?--user=3Dxuchang,--message=3D'fms=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=B3=BB=E7=BB=9F'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../itools/core/annotation/FileStrategy.java | 7 +- ...Config.java => MinioPropertiesConfig.java} | 22 +- .../core/config/SwaggerAutoConfiguration.java | 41 --- .../com/itools/core/config/SwaggerConfig.java | 108 ------- .../context/FileStrategyServiceContext.java | 15 +- .../java/com/itools/core/em/FmsCodeBean.java | 1 + .../java/com/itools/core/em/FmsConstants.java | 11 +- .../java/com/itools/core/em/StrategyType.java | 2 +- .../core/service/FileHandleService.java | 22 ++ .../core/service/FileManagerService.java | 17 +- .../core/service/MinioClientService.java | 177 ++++++++++++ .../impl/FastDfsFileManagerServiceImpl.java | 17 +- .../impl/MinioClientServiceImpl.java} | 40 ++- .../impl/MinioFileManagerServiceImpl.java | 66 ++++- .../impl/NioFileManagerServiceImpl.java | 29 +- itools-fms/itools-fms-model/pom.xml | 6 + .../core/param/FmsUploadTokenParam.java | 10 +- .../core/result/FmsFileUploadResult.java | 22 +- .../core/result/FmsMultipartFileResult.java | 6 + .../itools/core/result/FmsRecordResult.java | 10 +- .../core/result/FmsUploadTokenResult.java | 10 +- itools-fms/itools-fms-server/pom.xml | 31 ++ .../itools/core/FileSystemApplication.java | 9 + .../FmsFileHandleStrategyController.java | 30 +- .../controller/FmsFileRecordController.java | 12 +- .../controller/FmsFileSystemController.java | 268 +++--------------- .../service/FmsFileHandleStrategyService.java | 10 + .../core/service/FmsFileSystemService.java | 69 ++++- .../itools/core/service/FmsRecordService.java | 9 +- .../service/impl/FileHandleServiceImpl.java | 38 ++- .../FmsFileHandleStrategyServiceImpl.java | 62 ++-- .../impl/FmsFileSystemServiceImpl.java | 245 ++++++++++++---- .../service/impl/FmsRecordServiceImpl.java | 21 +- .../src/main/resources/application-dev.yml | 24 +- 34 files changed, 886 insertions(+), 581 deletions(-) rename itools-fms/itools-fms-core/src/main/java/com/itools/core/config/{MinioConfig.java => MinioPropertiesConfig.java} (61%) delete mode 100644 itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java delete mode 100644 itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java create mode 100644 itools-fms/itools-fms-core/src/main/java/com/itools/core/service/MinioClientService.java rename itools-fms/itools-fms-core/src/main/java/com/itools/core/{utils/MinioUtil.java => service/impl/MinioClientServiceImpl.java} (95%) diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java index 57665e5..fd827fb 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java @@ -18,7 +18,10 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface FileStrategy { - - StrategyType value(); + /** + * 文件系统策略的值 + * @return + */ + StrategyType value() default StrategyType.NIO; } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioPropertiesConfig.java similarity index 61% rename from itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java rename to itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioPropertiesConfig.java index cb3ebe4..a31ec1c 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioPropertiesConfig.java @@ -5,20 +5,24 @@ import io.minio.errors.InvalidEndpointException; import io.minio.errors.InvalidPortException; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; /** * @project: itools-backend - * @description: + * @description: 配置了minio的文件策略才会引用 * @author: XUCHANG * @create: 2021-04-01 16:06 */ @Data @Component +@ConditionalOnProperty(prefix = "fms",name = "strategy",havingValue = "minio") @ConfigurationProperties(prefix = "fms.minio") -public class MinioConfig { +@Log4j2 +public class MinioPropertiesConfig { @ApiModelProperty("endPoint是一个URL,域名,IPv4或者IPv6地址") private String endpoint; @@ -42,8 +46,18 @@ public class MinioConfig { private String configDir; @Bean - public MinioClient getMinioClient() throws InvalidEndpointException, InvalidPortException { - MinioClient minioClient = new MinioClient(endpoint, port, accessKey, secretKey,secure); + @ConditionalOnProperty(prefix = "fms",name = "strategy",havingValue = "minio") + public MinioClient initMinioClient() { + MinioClient minioClient = null; + log.info("初始化注入MinioClient"); + try { + minioClient = new MinioClient(endpoint, port, accessKey, secretKey,secure); + } catch (InvalidEndpointException e) { + e.printStackTrace(); + } catch (InvalidPortException e) { + e.printStackTrace(); + } return minioClient; } + } \ No newline at end of file diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java deleted file mode 100644 index ddd193e..0000000 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java +++ /dev/null @@ -1,41 +0,0 @@ -//package com.itools.core.config; -// -//import io.swagger.annotations.ApiOperation; -//import io.swagger.annotations.Contact; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import springfox.documentation.builders.ApiInfoBuilder; -//import springfox.documentation.builders.PathSelectors; -//import springfox.documentation.builders.RequestHandlerSelectors; -//import springfox.documentation.service.ApiInfo; -//import springfox.documentation.spi.DocumentationType; -//import springfox.documentation.spring.web.plugins.Docket; -//import springfox.documentation.swagger2.annotations.EnableSwagger2; -// -//@Configuration -//@EnableSwagger2 -//public class SwaggerAutoConfiguration{ -// -// @Bean -// public Docket createRestApi() { -// return new Docket(DocumentationType.SWAGGER_2) -// .groupName("") -// .apiInfo(apiInfo()) -// .select() -// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) -// .paths(PathSelectors.any()) -// .build(); -// } -// -// -// private ApiInfo apiInfo() { -// return new ApiInfoBuilder() -// .title("**平台对外接口") -// .description("1.提供**后台使用的接口 2.提供对其他服务调用的服务") -//// .contact(new Contact("xtj332", "https://blog.csdn.net/xtj332", "xtj332111@163.com")) -// .version("1.0") -// .build(); -// } -// -// -//} \ No newline at end of file diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java deleted file mode 100644 index b19297e..0000000 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java +++ /dev/null @@ -1,108 +0,0 @@ -//package com.itools.core.config; -// -//import io.swagger.annotations.ApiOperation; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.context.annotation.Profile; -//import springfox.documentation.builders.ApiInfoBuilder; -//import springfox.documentation.builders.ParameterBuilder; -//import springfox.documentation.builders.PathSelectors; -//import springfox.documentation.builders.RequestHandlerSelectors; -//import springfox.documentation.schema.ModelRef; -//import springfox.documentation.service.*; -//import springfox.documentation.spi.DocumentationType; -//import springfox.documentation.spi.service.contexts.SecurityContext; -//import springfox.documentation.spring.web.plugins.Docket; -//import springfox.documentation.swagger2.annotations.EnableSwagger2; -// -//import java.time.LocalTime; -//import java.util.ArrayList; -//import java.util.List; -// -///** -// * SwaggerConfig api文档地址:/swagger-ui.html 或者 /doc.html -// */ -////指定在某些环境启用swagger的配置 -//@Profile({ -// "dev","test" -//}) -//// swagger暂不支持webflux -//@Configuration -//@EnableSwagger2 -//public class SwaggerConfig { -// @Bean -// public Docket createRestApi() { -// //定义swagger全局入参token -// ParameterBuilder tokenPar = new ParameterBuilder(); -// List pars = new ArrayList(); -// tokenPar.name("Authorization").description("用户令牌(无须鉴权的可以不传 格式:bearer 密文串").modelRef(new ModelRef("string")) -// .parameterType("header").required(false).build(); -// pars.add(tokenPar.build()); -// -// return new Docket(DocumentationType.SWAGGER_2) -// .directModelSubstitute(LocalTime.class, String.class) -// //.groupName("normal") //使用默认分组,便于网关层的swagger转发 -// .apiInfo(defaultTitleInfo()) //可设置默认分组api顶部说明文字 -// .useDefaultResponseMessages(false) -// .select() -// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) -// //只允许生成ApiOperation注解的方法,其他系统内部用的api可隐藏 -// .build(); -//// //.globalOperationParameters(pars); -//// //设置安全模式,swagger全局设置token -//// .securitySchemes(securitySchemes()) -//// .securityContexts(securityContexts()); -// -// } -// -// /** -// * 安全模式,这里指定token通过Authorization头请求头传递 -// */ -// private List securitySchemes() -// { -// List apiKeyList = new ArrayList<>(); -// apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); -// return apiKeyList; -// } -// -// /** -// * 安全上下文 -// */ -// private List securityContexts() -// { -// List securityContexts = new ArrayList<>(); -// securityContexts.add( -// SecurityContext.builder() -// .securityReferences(defaultAuth()) -// .forPaths(PathSelectors.regex("^(?!auth).*$")) -// .build()); -// return securityContexts; -// } -// -// /** -// * 默认的安全上引用 -// */ -// private List defaultAuth() -// { -// AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); -// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; -// authorizationScopes[0] = authorizationScope; -// List securityReferences = new ArrayList<>(); -// securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); -// return securityReferences; -// } -// -// /** -// * 默认标题信息 -// * @return - -// */ -// private ApiInfo defaultTitleInfo() { -// return new ApiInfoBuilder() -// .title("接口地址使用Base URL")//大标题 -// .description("· 接口成功返回:{\"success\": true,\"code\": 20000,\"message\": \"成功\",\"data\": null} " -// + "
· 失败的返回:{\"success\": false,\"code\": 50002,\"message\": \"算术运算异常\",\"data\": null} " -// )//详细描述 -// .version("1.0")//版本 -// .build(); -// } -//} \ No newline at end of file diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java index b0a5438..8c01f0f 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java @@ -3,6 +3,7 @@ package com.itools.core.context; import com.itools.core.em.StrategyType; import com.itools.core.service.FileManagerService; import lombok.Getter; +import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @@ -17,6 +18,7 @@ import java.util.Map; * @create: 2021-04-01 16:02 */ @Component +@Log4j2 public class FileStrategyServiceContext { @Autowired private Environment environment; @@ -37,10 +39,17 @@ public class FileStrategyServiceContext { */ public FileManagerService get(){ boolean containsProperty = environment.containsProperty("fms.strategy"); - if (containsProperty){ - fileServiceMap.get(environment.getProperty("fms.strategy")); + if (!containsProperty){ + log.info("默认使用NIO策略"); + return fileServiceMap.get(StrategyType.NIO.getType()); } - return fileServiceMap.get(StrategyType.NIO.getType()); + String strategy = environment.getProperty("fms.strategy"); + if (!fileServiceMap.containsKey(strategy)){ + log.info("输入的文件系统策略不存在,请输入合法文件策略,默认使用NIO策略"); + return fileServiceMap.get(StrategyType.NIO.getType()); + } + log.info("文件系统策略使用{}策略",strategy); + return fileServiceMap.get(strategy); } public void put(String type, FileManagerService calcService) { diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java index 894387e..a544022 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java @@ -60,6 +60,7 @@ public class FmsCodeBean { FILE_MULTIPART_UPLOAD("FMSCODE13", "批量上传文件失败"), FAIL_FILE_TOKEN("FMSCODE14", "上传申请的TOKEN无效,请重新申请!"), FILE_TOKEN_NOT_NULL("FMSCODE15", "文件访问的TOKEN不能为空"), + FAIL_UPLOAD_FILE_TO_MINIO("FMSCODE16", "文件上传到服务器失败,请联系管理员!"), ; public final String code; diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java index 50badfb..34834ce 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java @@ -9,7 +9,7 @@ public class FmsConstants { /** * 文件记录的KEY */ - public static final String FSS_RECORD_ID_SEQ_NAME="FSS:FssRecord:ID"; + public static final String FSS_RECORD_ID_SEQ_NAME="fms:record:id"; /** * 文件申请上传的token的名称空间 */ @@ -18,6 +18,13 @@ public class FmsConstants { * 文件通用类型 */ public static final String FILE_CURRENCY_TYPE="currency"; - + /** + * 文件展示 + */ + public static final String SHOW = "show"; + /** + * 文件上传 + */ + public static final String DOWNLOAD = "download"; } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java index 85be616..0d6565a 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java @@ -10,7 +10,7 @@ import com.itools.core.utils.StringUtils; */ public enum StrategyType { NIO("nio", "NIO","nioFileManagerServiceImpl"), - MINIO("minio", "miniio文件系统","minioFileManagerServiceImpl"), + MINIO("minio", "minio文件系统","minioFileManagerServiceImpl"), FASTDFS("fastdfs", "fastdfs文件系统","fastDfsFileManagerServiceImpl"); private String type; private String desc; diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileHandleService.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileHandleService.java index 8d50488..40c560f 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileHandleService.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileHandleService.java @@ -3,9 +3,12 @@ package com.itools.core.service; import com.itools.core.base.CommonResult; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.result.FmsUploadTokenResult; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -30,4 +33,23 @@ public interface FileHandleService { * @return */ CommonResult saveFileForNio(MultipartFile file, FmsUploadTokenParam param, String uploadToken, String originalFilename); + + /** + * 文件策略为NIO + * 执行文件写入和上传 + * @param files 文件 + * @param uploadToken 访问token + * @param uploadTokenParam 上传参数,文件的限制 + * @return + */ + CommonResult> saveFileForNio(MultipartFile[] files, String uploadToken, FmsUploadTokenParam uploadTokenParam); + + /** + * 将文件持久化到数据库 + * @param file 文件 + * @param fmsUploadTokenParam 文件的类型等信息 + * @param uuid 文件唯一id + * @return + */ + CommonResult createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid); } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java index 42a99d3..263e6df 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java @@ -4,8 +4,11 @@ import com.itools.core.base.CommonResult; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @description: * @author: XUCHANG @@ -16,24 +19,22 @@ public interface FileManagerService { * 批量上传文件 * @param files 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 - * @param originalFilename 原名称 + * @param uploadTokenParam 文件的类型,以及限制条件 * @return */ - CommonResult mutipartUploadFiles(MultipartFile files, - String uploadToken, - FmsBusinessTypeResult businessType, - String originalFilename); + CommonResult> mutipartUploadFiles(MultipartFile[] files, + String uploadToken, + FmsUploadTokenParam uploadTokenParam); /** * 单个上传文件 * @param file 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 + * @param uploadTokenParam 文件的类型,以及限制条件 * @param originalFilename 原名称 * @return */ CommonResult singletonUploadFiles(MultipartFile file, String uploadToken, - FmsBusinessTypeResult businessType, + FmsUploadTokenParam uploadTokenParam, String originalFilename); } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/MinioClientService.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/MinioClientService.java new file mode 100644 index 0000000..343bfb7 --- /dev/null +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/MinioClientService.java @@ -0,0 +1,177 @@ +package com.itools.core.service; + +import io.minio.ObjectStat; +import io.minio.Result; +import io.minio.messages.Bucket; +import io.minio.messages.Item; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.util.List; + +/** + * @project: itools-backend + * @description: + * @author: XUCHANG + * @create: 2021-04-07 15:29 + */ +public interface MinioClientService { + /** + * 检查存储桶是否存在 + * @param bucketName + * @return + */ + boolean bucketExists(String bucketName); + + /** + * 创建存储桶 + * @param bucketName + * @return + */ + boolean makeBucket(String bucketName); + + /** + * 列出所有存储桶名称 + * @return + */ + List listBucketNames(); + + /** + * 列出所有存储桶 + * @return + */ + List listBuckets(); + + /** + * 删除存储桶 + * @param bucketName 存储桶名称 + * @return + */ + boolean removeBucket(String bucketName); + /** + * 列出存储桶中的所有对象名称 + * + * @param bucketName 存储桶名称 + * @return + */ + List listObjectNames(String bucketName); + /** + * 列出存储桶中的所有对象 + * + * @param bucketName 存储桶名称 + * @return + */ + Iterable> listObjects(String bucketName); + /** + * 通过文件上传到对象 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param fileName File name + * @return + */ + boolean putObject(String bucketName, String objectName, String fileName); + /** + * 文件上传 + * + * @param bucketName + * @param multipartFile + */ + void putObject(String bucketName, MultipartFile multipartFile, String filename); + /** + * 通过InputStream上传对象 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param stream 要上传的流 + * @return + */ + boolean putObject(String bucketName, String objectName, InputStream stream); + /** + * 以流的形式获取一个文件对象 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @return + */ + InputStream getObject(String bucketName, String objectName); + /** + * 以流的形式获取一个文件对象(断点下载) + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param offset 起始字节的位置 + * @param length 要读取的长度 (可选,如果无值则代表读到文件结尾) + * @return + */ + InputStream getObject(String bucketName, String objectName, long offset, Long length); + /** + * 下载并将文件保存到本地 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param fileName File name + * @return + */ + boolean getObject(String bucketName, String objectName, String fileName); + /** + * 删除一个对象 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + */ + boolean removeObject(String bucketName, String objectName); + /** + * 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表 + * + * @param bucketName 存储桶名称 + * @param objectNames 含有要删除的多个object名称的迭代器对象 + * @return + */ + List removeObject(String bucketName, List objectNames); + /** + * 生成一个给HTTP GET请求用的presigned URL。 + * 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 + * @return + */ + String presignedGetObject(String bucketName, String objectName, Integer expires); + /** + * 生成一个给HTTP PUT请求用的presigned URL。 + * 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 + * @return + */ + String presignedPutObject(String bucketName, String objectName, Integer expires); + /** + * 获取对象的元数据 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @return + */ + ObjectStat statObject(String bucketName, String objectName); + /** + * 文件访问路径 + * + * @param bucketName 存储桶名称 + * @param objectName 存储桶里的对象名称 + * @return + */ + String getObjectUrl(String bucketName, String objectName); + /** + * 下载文件 + * @param bucketName + * @param fileName + * @param originalName + * @param response + */ + void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response); +} diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java index 8b59e43..dec48e0 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java @@ -6,9 +6,12 @@ import com.itools.core.em.StrategyType; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.service.FileManagerService; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -21,15 +24,13 @@ public class FastDfsFileManagerServiceImpl implements FileManagerService { * 批量上传文件 * @param files 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 - * @param originalFilename 原名称 + * @param uploadTokenParam 文件的类型,以及限制条件 * @return */ @Override - public CommonResult mutipartUploadFiles(MultipartFile files, - String uploadToken, - FmsBusinessTypeResult businessType, - String originalFilename) { + public CommonResult> mutipartUploadFiles(MultipartFile[] files, + String uploadToken, + FmsUploadTokenParam uploadTokenParam) { return null; } @@ -38,14 +39,14 @@ public class FastDfsFileManagerServiceImpl implements FileManagerService { * * @param file 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 + * @param uploadTokenParam 文件的类型,以及限制条件 * @param originalFilename 原名称 * @return */ @Override public CommonResult singletonUploadFiles(MultipartFile file, String uploadToken, - FmsBusinessTypeResult businessType, + FmsUploadTokenParam uploadTokenParam, String originalFilename) { return null; } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioClientServiceImpl.java similarity index 95% rename from itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java rename to itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioClientServiceImpl.java index 561de3f..85321c5 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioClientServiceImpl.java @@ -1,5 +1,7 @@ -package com.itools.core.utils; +package com.itools.core.service.impl; +import com.itools.core.service.MinioClientService; +import com.itools.core.system.AbstractService; import io.minio.MinioClient; import io.minio.ObjectStat; import io.minio.PutObjectOptions; @@ -12,7 +14,7 @@ import io.minio.messages.Item; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; @@ -35,10 +37,10 @@ import java.util.List; * @author: XUCHANG * @create: 2021-04-01 16:06 */ -@Component -public class MinioUtil { +@Service +public class MinioClientServiceImpl extends AbstractService implements MinioClientService { - @Autowired + @Autowired(required = false) private MinioClient minioClient; private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600; @@ -49,6 +51,7 @@ public class MinioUtil { * @param bucketName 存储桶名称 * @return */ + @Override @SneakyThrows public boolean bucketExists(String bucketName) { boolean flag = false; @@ -64,6 +67,7 @@ public class MinioUtil { * * @param bucketName 存储桶名称 */ + @Override @SneakyThrows public boolean makeBucket(String bucketName) { boolean flag = bucketExists(bucketName); @@ -80,6 +84,7 @@ public class MinioUtil { * * @return */ + @Override @SneakyThrows public List listBucketNames() { List bucketList = listBuckets(); @@ -95,6 +100,7 @@ public class MinioUtil { * * @return */ + @Override @SneakyThrows public List listBuckets() { return minioClient.listBuckets(); @@ -106,6 +112,7 @@ public class MinioUtil { * @param bucketName 存储桶名称 * @return */ + @Override @SneakyThrows public boolean removeBucket(String bucketName) { boolean flag = bucketExists(bucketName); @@ -135,6 +142,7 @@ public class MinioUtil { * @param bucketName 存储桶名称 * @return */ + @Override @SneakyThrows public List listObjectNames(String bucketName) { List listObjectNames = new ArrayList<>(); @@ -155,6 +163,7 @@ public class MinioUtil { * @param bucketName 存储桶名称 * @return */ + @Override @SneakyThrows public Iterable> listObjects(String bucketName) { boolean flag = bucketExists(bucketName); @@ -172,6 +181,7 @@ public class MinioUtil { * @param fileName File name * @return */ + @Override @SneakyThrows public boolean putObject(String bucketName, String objectName, String fileName) { boolean flag = bucketExists(bucketName); @@ -192,6 +202,7 @@ public class MinioUtil { * @param bucketName * @param multipartFile */ + @Override @SneakyThrows public void putObject(String bucketName, MultipartFile multipartFile, String filename) { PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE); @@ -207,6 +218,7 @@ public class MinioUtil { * @param stream 要上传的流 * @return */ + @Override @SneakyThrows public boolean putObject(String bucketName, String objectName, InputStream stream) { boolean flag = bucketExists(bucketName); @@ -227,6 +239,7 @@ public class MinioUtil { * @param objectName 存储桶里的对象名称 * @return */ + @Override @SneakyThrows public InputStream getObject(String bucketName, String objectName) { boolean flag = bucketExists(bucketName); @@ -249,6 +262,7 @@ public class MinioUtil { * @param length 要读取的长度 (可选,如果无值则代表读到文件结尾) * @return */ + @Override @SneakyThrows public InputStream getObject(String bucketName, String objectName, long offset, Long length) { boolean flag = bucketExists(bucketName); @@ -270,6 +284,7 @@ public class MinioUtil { * @param fileName File name * @return */ + @Override @SneakyThrows public boolean getObject(String bucketName, String objectName, String fileName) { boolean flag = bucketExists(bucketName); @@ -289,6 +304,7 @@ public class MinioUtil { * @param bucketName 存储桶名称 * @param objectName 存储桶里的对象名称 */ + @Override @SneakyThrows public boolean removeObject(String bucketName, String objectName) { boolean flag = bucketExists(bucketName); @@ -306,6 +322,7 @@ public class MinioUtil { * @param objectNames 含有要删除的多个object名称的迭代器对象 * @return */ + @Override @SneakyThrows public List removeObject(String bucketName, List objectNames) { List deleteErrorNames = new ArrayList<>(); @@ -329,6 +346,7 @@ public class MinioUtil { * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 * @return */ + @Override @SneakyThrows public String presignedGetObject(String bucketName, String objectName, Integer expires) { boolean flag = bucketExists(bucketName); @@ -352,6 +370,7 @@ public class MinioUtil { * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 * @return */ + @Override @SneakyThrows public String presignedPutObject(String bucketName, String objectName, Integer expires) { boolean flag = bucketExists(bucketName); @@ -373,6 +392,7 @@ public class MinioUtil { * @param objectName 存储桶里的对象名称 * @return */ + @Override @SneakyThrows public ObjectStat statObject(String bucketName, String objectName) { boolean flag = bucketExists(bucketName); @@ -390,6 +410,7 @@ public class MinioUtil { * @param objectName 存储桶里的对象名称 * @return */ + @Override @SneakyThrows public String getObjectUrl(String bucketName, String objectName) { boolean flag = bucketExists(bucketName); @@ -401,7 +422,14 @@ public class MinioUtil { } - + /** + * 下载文件 + * @param bucketName + * @param fileName + * @param originalName + * @param response + */ + @Override public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) { try { diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java index 7b8215b..a065b7d 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java @@ -2,13 +2,28 @@ package com.itools.core.service.impl; import com.itools.core.annotation.FileStrategy; import com.itools.core.base.CommonResult; +import com.itools.core.em.FmsCodeBean; +import com.itools.core.em.FmsConstants; import com.itools.core.em.StrategyType; +import com.itools.core.exception.AppException; import com.itools.core.param.FmsUploadTokenParam; -import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; +import com.itools.core.service.FileHandleService; import com.itools.core.service.FileManagerService; +import com.itools.core.service.MinioClientService; +import com.itools.core.system.AbstractService; +import com.itools.core.utils.UUIDUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -16,20 +31,28 @@ import org.springframework.web.multipart.MultipartFile; * @create: 2021-04-01 16:17 */ @FileStrategy(value = StrategyType.MINIO) -public class MinioFileManagerServiceImpl implements FileManagerService { +public class MinioFileManagerServiceImpl extends AbstractService implements FileManagerService { + @Autowired + private MinioClientService minioClientService; + @Autowired + private Environment environment; + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${fms.file.store-root-path}") + String fileStoreRootPath; + @Autowired + private FileHandleService fileHandleService; /** * 批量上传文件 * @param files 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 - * @param originalFilename 原名称 + * @param uploadTokenParam 文件的类型,以及限制条件 * @return */ @Override - public CommonResult mutipartUploadFiles(MultipartFile files, - String uploadToken, - FmsBusinessTypeResult businessType, - String originalFilename) { + public CommonResult> mutipartUploadFiles(MultipartFile[] files, + String uploadToken, + FmsUploadTokenParam uploadTokenParam) { return null; } @@ -38,15 +61,36 @@ public class MinioFileManagerServiceImpl implements FileManagerService { * * @param file 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 + * @param uploadTokenParam 文件的类型,以及限制条件 * @param originalFilename 原名称 * @return */ @Override + @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public CommonResult singletonUploadFiles(MultipartFile file, String uploadToken, - FmsBusinessTypeResult businessType, + FmsUploadTokenParam uploadTokenParam, String originalFilename) { - return null; + //文件记录写入数据库 + String uniqueId = UUIDUtils.uuid(); + fileHandleService.createAndPersistDBRecord(file,uploadTokenParam,uniqueId); + try { + //执行单个文件上传到minio服务器、 + boolean bucketExists = minioClientService.bucketExists(fileStoreRootPath); + if (!bucketExists){ + minioClientService.makeBucket(fileStoreRootPath); + } + minioClientService.putObject(fileStoreRootPath,file,uniqueId); + }catch (Exception e){ + logger.error("文件上传到MINIO服务器失败",e); + throw new AppException(FmsCodeBean.FmsCode.FAIL_UPLOAD_FILE_TO_MINIO.getCode()); + } + + //文件上传成功,删除文件访问的token + stringRedisTemplate.delete(FmsConstants.FILE_TOKEN_NAME_SPACE + uploadToken); + FmsFileUploadResult result = new FmsFileUploadResult(); + result.setUniqueId(uniqueId); + result.setFileName(originalFilename); + return CommonResult.success(result); } } diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java index 4631913..f00f521 100644 --- a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java +++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java @@ -7,6 +7,7 @@ import com.itools.core.log.Logable; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.service.FileHandleService; import com.itools.core.service.FileManagerService; import org.springframework.beans.BeanUtils; @@ -15,6 +16,8 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -29,16 +32,17 @@ public class NioFileManagerServiceImpl implements FileManagerService { * 批量上传文件 * @param files 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 - * @param originalFilename 原名称 + * @param uploadTokenParam 文件的类型,以及限制条件 * @return */ @Override - public CommonResult mutipartUploadFiles(MultipartFile files, - String uploadToken, - FmsBusinessTypeResult businessType, - String originalFilename) { - return null; + @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) + public CommonResult> mutipartUploadFiles(MultipartFile[] files, + String uploadToken, + FmsUploadTokenParam uploadTokenParam) { + + //执行上传文件的操作 + return fileHandleService.saveFileForNio(files,uploadToken,uploadTokenParam); } /** @@ -46,7 +50,7 @@ public class NioFileManagerServiceImpl implements FileManagerService { * * @param file 文件 * @param uploadToken 文件的token - * @param businessType 文件的类型,以及限制条件 + * @param uploadTokenParam 文件的类型,以及限制条件 * @param originalFilename 原名称 * @return */ @@ -55,12 +59,9 @@ public class NioFileManagerServiceImpl implements FileManagerService { @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public CommonResult singletonUploadFiles(MultipartFile file, String uploadToken, - FmsBusinessTypeResult businessType, + FmsUploadTokenParam uploadTokenParam, String originalFilename) { - FmsUploadTokenParam param = new FmsUploadTokenParam(); - BeanUtils.copyProperties(businessType , param); - param.setOriginalFilename(originalFilename); - CommonResult fmsFileUploadResultCommonResult = fileHandleService.saveFileForNio(file, param, uploadToken, originalFilename); - return fmsFileUploadResultCommonResult; + + return fileHandleService.saveFileForNio(file, uploadTokenParam, uploadToken, originalFilename); } } diff --git a/itools-fms/itools-fms-model/pom.xml b/itools-fms/itools-fms-model/pom.xml index f7be9ab..8441765 100644 --- a/itools-fms/itools-fms-model/pom.xml +++ b/itools-fms/itools-fms-model/pom.xml @@ -28,6 +28,12 @@ org.projectlombok lombok + + io.swagger + swagger-annotations + 1.5.9 + compile + \ No newline at end of file diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java index fb5b2c4..2ae2233 100644 --- a/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java +++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java @@ -10,18 +10,18 @@ import com.itools.core.result.FmsBusinessTypeResult; */ public class FmsUploadTokenParam { - private FmsBusinessTypeResult fsBusinessType; + private FmsBusinessTypeResult businessTypeResult; private String fromSystemId; private String needEncrypt; private String remark; private String originalFilename; - public FmsBusinessTypeResult getFsBusinessType() { - return fsBusinessType; + public FmsBusinessTypeResult getBusinessTypeResult() { + return businessTypeResult; } - public void setFsBusinessType(FmsBusinessTypeResult fsBusinessType) { - this.fsBusinessType = fsBusinessType; + public void setBusinessTypeResult(FmsBusinessTypeResult businessTypeResult) { + this.businessTypeResult = businessTypeResult; } public String getFromSystemId() { diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java index 675c018..294a810 100644 --- a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java +++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java @@ -1,15 +1,27 @@ package com.itools.core.result; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + /** * @Author XUCHANG * @description: * @Date 2020/11/5 14:35 */ -public class FmsFileUploadResult { +@ApiModel("文件上传返回实体类") +public class FmsFileUploadResult implements Serializable { /** * 成功时必填,该文件的唯一ID */ + @ApiModelProperty("成功时必填,该文件的唯一ID") private String uniqueId; + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String fileName; public String getUniqueId() { return uniqueId; @@ -18,4 +30,12 @@ public class FmsFileUploadResult { public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } } diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java index 9d6b560..6a1d8dd 100644 --- a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java +++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java @@ -1,5 +1,8 @@ package com.itools.core.result; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + import java.io.Serializable; /** @@ -7,14 +10,17 @@ import java.io.Serializable; * @description: * @Date 2020/11/4 18:01 */ +@ApiModel("文件上传返回实体类") public class FmsMultipartFileResult implements Serializable { /** * 文件访问唯一id */ + @ApiModelProperty("成功时必填,该文件的唯一ID") private String uniqueId; /** * 文件名称 */ + @ApiModelProperty("文件名称") private String fileName; public String getUniqueId() { diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java index 470226e..11169c9 100644 --- a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java +++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java @@ -7,14 +7,14 @@ package com.itools.core.result; */ public class FmsRecordResult { - private FmsDetailRecordResult fssRecord; + private FmsDetailRecordResult recordResult; - public FmsDetailRecordResult getFssRecord() { - return fssRecord; + public FmsDetailRecordResult getRecordResult() { + return recordResult; } - public void setFssRecord(FmsDetailRecordResult fssRecord) { - this.fssRecord = fssRecord; + public void setRecordResult(FmsDetailRecordResult recordResult) { + this.recordResult = recordResult; } } diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java index 673b4ce..de45247 100644 --- a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java +++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java @@ -9,7 +9,7 @@ import java.io.Serializable; */ public class FmsUploadTokenResult implements Serializable { - private FmsBusinessTypeResult fsBusinessType; + private FmsBusinessTypeResult businessTypeResult; /** * 来源系统 */ @@ -23,12 +23,12 @@ public class FmsUploadTokenResult implements Serializable { */ private String remark; - public FmsBusinessTypeResult getFsBusinessType() { - return fsBusinessType; + public FmsBusinessTypeResult getBusinessTypeResult() { + return businessTypeResult; } - public void setFsBusinessType(FmsBusinessTypeResult fsBusinessType) { - this.fsBusinessType = fsBusinessType; + public void setBusinessTypeResult(FmsBusinessTypeResult businessTypeResult) { + this.businessTypeResult = businessTypeResult; } public String getFromSystemId() { diff --git a/itools-fms/itools-fms-server/pom.xml b/itools-fms/itools-fms-server/pom.xml index 9c50910..cf3bae0 100644 --- a/itools-fms/itools-fms-server/pom.xml +++ b/itools-fms/itools-fms-server/pom.xml @@ -54,6 +54,22 @@ com.baomidou mybatis-plus-generator + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.6 + mysql @@ -84,6 +100,21 @@ + + + + + + + + + + + + commons-fileupload + commons-fileupload + 1.3.2 + diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java index e562114..32603ea 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java @@ -12,6 +12,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; /** * @description: @@ -29,6 +30,14 @@ public class FileSystemApplication { springApplication.setBannerMode(Banner.Mode.OFF); springApplication.run(args); } + + @Bean(name = "multipartResolver") + public CommonsMultipartResolver getCommonsMultipartResolver() { + CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); + multipartResolver.setMaxUploadSize(20971520); + multipartResolver.setMaxInMemorySize(1048576); + return multipartResolver; + } @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileHandleStrategyController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileHandleStrategyController.java index c37bc8c..cbc3ed6 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileHandleStrategyController.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileHandleStrategyController.java @@ -1,26 +1,22 @@ package com.itools.core.controller; import com.itools.core.base.CommonResult; -import com.itools.core.em.FmsCodeBean; -import com.itools.core.exception.AppException; import com.itools.core.log.Logable; -import com.itools.core.param.FmsUploadTokenParam; -import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; -import com.itools.core.result.FmsUploadTokenResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.service.FmsFileHandleStrategyService; -import com.itools.core.utils.StringUtils; import com.itools.core.validate.ParamsValidate; +import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.hibernate.validator.constraints.NotBlank; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotNull; +import java.util.List; /** * @project: itools-backend @@ -29,7 +25,7 @@ import javax.validation.constraints.NotNull; * @create: 2021-04-05 14:43 */ @RestController -@ApiOperation("FmsFileHandleStrategyController") +@Api("文件系统处理策略服务接口") public class FmsFileHandleStrategyController { @Autowired private FmsFileHandleStrategyService fmsFileHandleStrategyService; @@ -50,8 +46,24 @@ public class FmsFileHandleStrategyController { @ParamsValidate(argsIndexs = {0,1}) public CommonResult singletonUploadFile(@NotNull(message = "FMSCODE03") MultipartFile file, @NotBlank(message = "FMSCODE15") String uploadToken) { - return fmsFileHandleStrategyService.singletonUploadFile(file,uploadToken); } + /** + * 返回文件对应的唯一ID + * 文件批量上传 + * @param files 文件 + * @param uploadToken 申请的token + * @return + */ + @PostMapping("/multipart/upload/file") + @ApiOperation(value = "批量上传文件", notes = "批量上传文件", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(name = "uploadToken", value = "文件上传token", required = true, dataType = "String", paramType = "query") + }) + public CommonResult> filesMultipartUpload(@RequestParam("files") MultipartFile[] files, + String uploadToken) { + return fmsFileHandleStrategyService.filesMultipartUpload(files,uploadToken); + } + } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java index 0ad6405..66c3212 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java @@ -6,6 +6,7 @@ import com.itools.core.log.Logable; import com.itools.core.result.FmsRecordResult; import com.itools.core.result.FmsDetailRecordResult; import com.itools.core.service.FmsRecordService; +import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -21,7 +22,7 @@ import java.io.IOException; * @create: 2021-04-01 11:26 */ @RestController -@ApiOperation("FmsFileRecordController") +@Api("文件记录信息接口") public class FmsFileRecordController { @Autowired @@ -32,13 +33,10 @@ public class FmsFileRecordController { * @return * @throws IOException */ - @RequestMapping(value = "/fssRecord", method = RequestMethod.GET) + @RequestMapping(value = "/get/record", method = RequestMethod.GET) @Logable @ApiOperation(value = "获取文件记录信息", notes = "获取文件记录信息", httpMethod = "GET") - public CommonResult queryFssRecordByUniqueId(@RequestParam("uniqueId") String uniqueId) { - FmsRecordResult response = new FmsRecordResult(); - FmsDetailRecordResult record = fmsRecordService.queryFssRecordByUniqueId(uniqueId); - response.setFssRecord(record); - return CommonResult.success(response); + public CommonResult queryFssRecordByUniqueId(@RequestParam("uniqueId") String uniqueId) { + return fmsRecordService.queryFssRecordByUniqueId(uniqueId); } } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java index b41ece8..09e2312 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java @@ -1,41 +1,19 @@ package com.itools.core.controller; import com.itools.core.base.CommonResult; -import com.itools.core.context.FileStrategyServiceContext; -import com.itools.core.em.FmsCodeBean; -import com.itools.core.exception.AppException; import com.itools.core.log.Logable; -import com.itools.core.param.FmsAccessTokenParam; -import com.itools.core.param.FmsUploadTokenParam; -import com.itools.core.param.FmsBusinessTypeParam; import com.itools.core.request.FmsBase64FileUploadRequest; import com.itools.core.result.*; -import com.itools.core.service.FileHandleService; -import com.itools.core.service.FmsAccessTokenService; -import com.itools.core.service.FmsBusinessTypeService; import com.itools.core.service.FmsFileSystemService; -import com.itools.core.utils.Base64Utils; -import com.itools.core.utils.StringUtils; -import com.itools.core.utils.ZipUtils; -import com.itools.core.validate.ParamsValidate; +import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; -import org.hibernate.validator.constraints.NotBlank; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import sun.misc.BASE64Encoder; import javax.servlet.http.HttpServletResponse; -import javax.validation.constraints.NotNull; import java.io.*; -import java.net.URLEncoder; -import java.util.ArrayList; import java.util.List; /** * @description: @@ -43,27 +21,11 @@ import java.util.List; * @create: 2021-04-01 11:26 */ @RestController -@ApiOperation("FmsFileSystemController") +@Api("文件控制访问接口") public class FmsFileSystemController { - @Autowired - private FmsBusinessTypeService fmsBusinessTypeService; - - @Autowired - private FmsAccessTokenService fmsAccessTokenService; - @Autowired private FmsFileSystemService fmsFileSystemService; - @Autowired - private FileStrategyServiceContext fileStrategyServiceContext; - @Autowired - private FileHandleService fileHandleService; - - private static final String SHOW = "show"; - - private static final String DOWNLOAD = "download"; - - private static final Logger LOGGER = LoggerFactory.getLogger(FmsFileSystemController.class); /** * 申请文件上传token @@ -90,8 +52,15 @@ public class FmsFileSystemController { return fmsFileSystemService.applyUploadToken(businessType, fromSystemId, needEncrypt, remark); } - - @PostMapping("FilePath") + /** + * 获取文件访问路径 + * @param uniqueId + * @param expiredTime + * @param maxAccessCount + * @param type + * @return + */ + @PostMapping("/get/file/path") @Logable @ApiOperation(value = "获取文件访问路径", notes = "获取文件访问路径", httpMethod = "POST") @ApiImplicitParams({ @@ -101,11 +70,18 @@ public class FmsFileSystemController { @ApiImplicitParam(name = "type", value = "文件下载 download/展示 show", required = true, dataType = "String", paramType = "query") }) public CommonResult getFileAccessUrl(String uniqueId, Integer expiredTime, @RequestParam(defaultValue = "-1", required = false) int maxAccessCount, String type) { - String fileUrlByFileId = fmsFileSystemService.getFileUrlByFileId(uniqueId, expiredTime, maxAccessCount, type); - return CommonResult.success(fileUrlByFileId); + return fmsFileSystemService.getFileUrlByFileId(uniqueId, expiredTime, maxAccessCount, type); } - @PostMapping("FilesPath") + /** + * 获取文件访问路径 + * @param uniqueIds + * @param expiredTime + * @param maxAccessCount + * @param type + * @return + */ + @PostMapping("/get/files/path") @Logable @ApiOperation(value = "获取文件访问路径", notes = "获取文件访问路径", httpMethod = "POST") @ApiImplicitParams({ @@ -114,65 +90,33 @@ public class FmsFileSystemController { @ApiImplicitParam(name = "maxAccessCount", value = "最大访问次数", required = false, dataType = "Long", paramType = "query"), @ApiImplicitParam(name = "type", value = "文件下载 download/展示 show", required = true, dataType = "String", paramType = "query") }) - public CommonResult getFileAccessUrl(@RequestParam(value = "uniqueIds",required = false) List uniqueIds, + public CommonResult> getFileAccessUrl(@RequestParam(value = "uniqueIds",required = false) List uniqueIds, @RequestParam(value = "expiredTime",required = false) Integer expiredTime, @RequestParam(value = "maxAccessCount",defaultValue = "-1", required = false) Integer maxAccessCount, @RequestParam(value = "type",required = false) String type) { return fmsFileSystemService.getFileUrlByFileIds(uniqueIds, expiredTime, maxAccessCount, type); } - @GetMapping("File/{uniqueId}") + /** + * 下载文件 + * @param uniqueId 文件唯一id + * @param fileAccessToken 文件的访问token + * @param response + */ + @ApiOperation(value = "下载文件", notes = "下载文件", httpMethod = "GET") + @GetMapping("/get/file/{uniqueId}") @Logable - public void downloadFile(@PathVariable String uniqueId, @RequestParam("fileAccessToken") String fileAccessToken, HttpServletResponse response) { - try { - FmsAccessTokenResult fsAccessToken = fmsAccessTokenService.getFileAccessToken(fileAccessToken); - if (fsAccessToken == null) { - throw new AppException(FmsCodeBean.FmsCode.INVALID_FS_TOKEN.code); - } - if (!uniqueId.equals(fsAccessToken.getUniqueId())) { - throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code); - } - FmsAccessTokenParam param = new FmsAccessTokenParam(); - BeanUtils.copyProperties(fsAccessToken , param); - FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(param, uniqueId, fileAccessToken); - String type = fsAccessToken.getType(); - if (SHOW.equals(type)) { - response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize()); - } else if (DOWNLOAD.equals(type)) { - // 设置文件名, 可用于下载 - response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize()); - response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fsUploadRecord.getOrigFileName(), "utf-8")); - } - response.setCharacterEncoding("UTF-8"); - response.setContentType(fsUploadRecord.getContentType()); - OutputStream outputStream = response.getOutputStream(); - FileCopyUtils.copy(new FileInputStream(fmsFileSystemService.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName())), outputStream); - } catch (AppException e) { - String errorCode = e.getErrorCode(); - response.setStatus(Integer.parseInt(errorCode)); - return; - } catch (IOException e) { - response.setStatus(500); - return; - } + public void downloadFile(@PathVariable String uniqueId, + @RequestParam("fileAccessToken") String fileAccessToken, + HttpServletResponse response) { + fmsFileSystemService.downloadFile(fileAccessToken,response,uniqueId); } - @GetMapping("File/getFileBase64") + @GetMapping("/get/file/base64") @Logable + @ApiOperation(value = "获取base64文件", notes = "获取base64文件", httpMethod = "GET") public CommonResult getFileBase64(@RequestParam("uniqueId")String uniqueId){ - FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(uniqueId); - try { - String path = fmsFileSystemService.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName()); - File file = new File(path); - FileInputStream fileInputStream = new FileInputStream(file); - byte[] buffer = new byte[(int)file.length()]; - fileInputStream.read(buffer); - fileInputStream.close(); - return CommonResult.success(new BASE64Encoder().encode(buffer)); - } catch (Exception e) { - LOGGER.error(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, e); - throw new AppException(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.message); - } + return fmsFileSystemService.getFileBase64(uniqueId); } /** @@ -182,147 +126,25 @@ public class FmsFileSystemController { */ @PostMapping("File/BaseSixFour") @Logable - @ApiOperation(value = "文件上传", notes = "文件上传", httpMethod = "POST") + @ApiOperation(value = "文件上传Base64", notes = "文件上传Base64", httpMethod = "POST") public CommonResult uploadFileBase64(@RequestBody FmsBase64FileUploadRequest base64Req) { - FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(base64Req.getUploadToken()); - if (fsUploadToken == null) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code); - } - FmsBusinessTypeResult fsBusinessType = fsUploadToken.getFsBusinessType(); - byte[] fileBytes; - try { - //将字符串转换为byte数组 - fileBytes = Base64Utils.decode(base64Req.getFileBaseSixFour()); - } catch (Exception e) { - throw new AppException(FmsCodeBean.FmsCode.FAIL.code); - } - - String fsSize = fsBusinessType.getFsSize(); - Long limitSize = Long.parseLong(fsSize); - long fileSize = fileBytes.length; - int mult = 1024; - if (fileSize > (limitSize * mult)) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code); - } - if (!fsBusinessType.getBusinessType().equals(base64Req.getBusinessType())) { - // 文件类型不一致 - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code); - } - FmsBusinessTypeParam fmsBusinessTypeParam = new FmsBusinessTypeParam(); - BeanUtils.copyProperties(fsBusinessType , fmsBusinessTypeParam); - FmsUploadTokenParam fmsUploadTokenParam = new FmsUploadTokenParam(); - BeanUtils.copyProperties(fsUploadToken , fmsUploadTokenParam); - String fileUploadResponse = fmsFileSystemService.saveFileFromBytes(fileBytes, base64Req.getFileName(), fmsBusinessTypeParam, fmsUploadTokenParam); - fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(base64Req.getUploadToken()); - return CommonResult.success(fileUploadResponse); - } - - /** - * 返回文件的唯一ID - * @param file - * @param uploadToken - * @return - */ - @PostMapping("File") - @Logable - @ApiOperation(value = "文件上传", notes = "文件上传", httpMethod = "POST") - @ApiImplicitParams({ - @ApiImplicitParam(name = "uploadToken", value = "文件上传token", required = true, dataType = "String", paramType = "query") - }) - @ParamsValidate(argsIndexs = {0,1}) - public CommonResult fileUpload(@RequestParam(value = "file")@NotNull(message = "FMSCODE03") MultipartFile file, - @RequestParam(value = "uploadToken") @NotBlank(message = "FMSCODE15") String uploadToken, - @RequestParam(value = "fileName",required = false)String fileName) { - //压缩过后的文件名称前端无法获取,额外的字段标识 - String originalFilename = file.getOriginalFilename(); - if (!StringUtils.isBlank(fileName)){ - originalFilename = fileName; - } - FmsFileUploadResult response = new FmsFileUploadResult(); - if (file == null || StringUtils.isBlank(originalFilename)) { - // 文件不能为空 - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILE_IS_NULL.code); - } - - FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(uploadToken); - if (fsUploadToken == null) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code); - } - FmsBusinessTypeResult fsBusinessType = fsUploadToken.getFsBusinessType(); - String fsSize = fsBusinessType.getFsSize(); - Long limitSize = Long.parseLong(fsSize); - long fileSize = file.getSize(); - int mult = 102400; - if (fileSize > (limitSize * mult)) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code); - } - String fsType = fsBusinessType.getFsType(); - if (StringUtils.equals(fsType, "currency")){ - //如果取值为currency,则不判断类型 - }else { - String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); - String contentType = file.getContentType(); - if (contentType == null || !fsType.contains(suffix.trim().toLowerCase()) || !fsType.contains(contentType)) { - LOGGER.error(FmsCodeBean.FmsCode.ERROR_FILETYPE.code, "文件类型:" + suffix + " || " + contentType); - // 文件后缀错误 - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code); - } - } - - FmsUploadTokenParam param = new FmsUploadTokenParam(); - BeanUtils.copyProperties(fsUploadToken , param); - param.setOriginalFilename(originalFilename); - String uniqueId = fmsFileSystemService.saveFile(file, param); - fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(uploadToken); - response.setUniqueId(uniqueId); - return CommonResult.success(response); + return fmsFileSystemService.uploadFileBase64(base64Req); } /** - * 文件批量上传 - * @param files 文件 - * @param uploadToken 申请的token - * @return + * 下载zip压缩文件接口 + * @param uniqueIds 文件唯一ids + * @param zipName 压缩文件名称 + * @param response + * @throws IOException */ - @PostMapping("/Files") - @Logable - @ApiOperation(value = "批量上传文件", notes = "批量上传文件", httpMethod = "POST") - @ApiImplicitParams({ - @ApiImplicitParam(name = "uploadToken", value = "文件上传token", required = true, dataType = "String", paramType = "query") - }) - public CommonResult filesMultipartUpload(@RequestPart(name = "files", required = true) MultipartFile[] files, String uploadToken) { - - return fmsFileSystemService.filesMultipartUpload(files,uploadToken); - } - @ApiOperation(value = "下载zip压缩文件接口", notes = "下载zip压缩文件接口", httpMethod = "GET") @Logable @RequestMapping(value = "/download/zip",method = RequestMethod.GET) public void downloadZipByUniqueIds(@RequestParam("uniqueIds") List uniqueIds, @RequestParam(value = "zipName", required = false) String zipName, HttpServletResponse response) throws IOException { - if (StringUtils.isBlank(zipName)) { - zipName = "attachment"; - } - List paths = new ArrayList<>(); - List files = new ArrayList<>(); - for (String uniqueId : uniqueIds) { - FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(uniqueId); - String path = fmsFileSystemService.getFileLocalPath(uniqueId, fsUploadRecord.getOrigFileName()); - paths.add(path); - File file = new File(path); - files.add(file); - } - try { - response.setContentType("application/zip"); - response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(zipName + ".zip", "utf-8")); - OutputStream outputStream = response.getOutputStream(); - ZipUtils.toZip(files, outputStream); - } catch (FileNotFoundException e) { - throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code); - } catch (Exception e) { - e.printStackTrace(); - } + fmsFileSystemService.downloadZipByUniqueIds(uniqueIds,zipName,response); } } \ No newline at end of file diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileHandleStrategyService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileHandleStrategyService.java index 7163714..c04163e 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileHandleStrategyService.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileHandleStrategyService.java @@ -2,8 +2,11 @@ package com.itools.core.service; import com.itools.core.base.CommonResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -18,4 +21,11 @@ public interface FmsFileHandleStrategyService { * @return */ CommonResult singletonUploadFile(MultipartFile file, String uploadToken); + /** + * 批量上传文件 + * @param files 文件 + * @param uploadToken 文件访问的token + * @return + */ + CommonResult> filesMultipartUpload(MultipartFile[] files, String uploadToken); } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java index 58d3009..713ffa1 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java @@ -4,10 +4,14 @@ import com.itools.core.base.CommonResult; import com.itools.core.param.FmsAccessTokenParam; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.param.FmsBusinessTypeParam; +import com.itools.core.request.FmsBase64FileUploadRequest; import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsDetailRecordResult; +import com.itools.core.result.FmsFileRecordPathResult; +import com.itools.core.result.FmsMultipartFileResult; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.List; /** @@ -32,10 +36,10 @@ public interface FmsFileSystemService { * 存储文件 * * @param file - * @param fsUploadToken + * @param fmsUploadTokenParam * @return */ - String saveFile(MultipartFile file, FmsUploadTokenParam fsUploadToken); + String saveFile(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam); @@ -71,19 +75,20 @@ public interface FmsFileSystemService { * @param uniqueId * @param expiredTime * @param maxAccessCount + * @param type * @return */ - String getFileUrlByFileId(String uniqueId, int expiredTime, int maxAccessCount, String type); + CommonResult getFileUrlByFileId(String uniqueId, int expiredTime, int maxAccessCount, String type); /** * 获得uniqueId对应的文件上传记录 * 会检查 - * @param fsAccessToken + * @param fmsAccessTokenParam * @param uniqueId * @param fileAccessToken * @return */ - FmsDetailRecordResult getFileUploadRecord(FmsAccessTokenParam fsAccessToken, String uniqueId, String fileAccessToken); + FmsDetailRecordResult getFileUploadRecord(FmsAccessTokenParam fmsAccessTokenParam, String uniqueId, String fileAccessToken); /** @@ -96,10 +101,10 @@ public interface FmsFileSystemService { /** * 文件批量上传 * @param files - * @param param + * @param fmsUploadTokenParam * @return */ - CommonResult uploadFiles(MultipartFile[] files, FmsUploadTokenParam param); + CommonResult> uploadFiles(MultipartFile[] files, FmsUploadTokenParam fmsUploadTokenParam); /** * 验证文件 @@ -107,14 +112,12 @@ public interface FmsFileSystemService { * @param fsBusinessType */ void verifyFiles(MultipartFile[] files, FmsBusinessTypeResult fsBusinessType); - /** - * 文件批量上传的业务逻辑 - * @param files - * @param uploadToken - * @return + * 验证文件 + * @param file + * @param fsBusinessType */ - CommonResult filesMultipartUpload(MultipartFile[] files, String uploadToken); + void verifyFiles(MultipartFile file, FmsBusinessTypeResult fsBusinessType); /** * 获取文件访问路径,如果超时时间设置为小于等于0,那么返回的有效路径可以永久访问 @@ -124,5 +127,43 @@ public interface FmsFileSystemService { * @param type * @return */ - CommonResult getFileUrlByFileIds(List uniqueIds, Integer expiredTime, int maxAccessCount, String type); + CommonResult> getFileUrlByFileIds(List uniqueIds, Integer expiredTime, int maxAccessCount, String type); + + /** + * 下载文件 + * @param fileAccessToken + * @param response + * @param uniqueId + */ + void downloadFile(String fileAccessToken, HttpServletResponse response, String uniqueId); + + /** + * 获取base64文件 + * @param uniqueId + * @return + */ + CommonResult getFileBase64(String uniqueId); + + /** + * 上传base64文件 + * @param base64Req + * @return + */ + CommonResult uploadFileBase64(FmsBase64FileUploadRequest base64Req); + + /** + * 下载zip压缩文件接口 + * @param uniqueIds + * @param zipName + * @param response + */ + void downloadZipByUniqueIds(List uniqueIds, String zipName, HttpServletResponse response); + /** + * 文件持久化到数据库 + * @param file + * @param fmsUploadTokenParam + * @param uuid + * @return + */ + String createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid); } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java index 0df6b92..aa15a5b 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java @@ -1,6 +1,7 @@ package com.itools.core.service; +import com.itools.core.base.CommonResult; import com.itools.core.result.FmsDetailRecordResult; /** @@ -10,7 +11,11 @@ import com.itools.core.result.FmsDetailRecordResult; */ public interface FmsRecordService { - - FmsDetailRecordResult queryFssRecordByUniqueId(String uniqueId); + /** + * 查询文件记录 + * @param uniqueId 文件唯一id + * @return + */ + CommonResult queryFssRecordByUniqueId(String uniqueId); } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FileHandleServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FileHandleServiceImpl.java index 622d570..ad46379 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FileHandleServiceImpl.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FileHandleServiceImpl.java @@ -7,6 +7,7 @@ import com.itools.core.em.FmsConstants; import com.itools.core.exception.AppException; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.result.FmsUploadTokenResult; import com.itools.core.service.FileHandleService; import com.itools.core.service.FmsAccessTokenService; @@ -22,6 +23,7 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.List; /** * @project: itools-backend @@ -79,11 +81,45 @@ public class FileHandleServiceImpl extends AbstractService implements FileHandle */ @Override public CommonResult saveFileForNio(MultipartFile file, FmsUploadTokenParam param, String uploadToken, String originalFilename) { - FmsFileUploadResult fmsFileUploadResult = new FmsFileUploadResult(); param.setOriginalFilename(originalFilename); String uniqueId = fmsFileSystemService.saveFile(file, param); + //文件上传成功,删除文件访问的token stringRedisTemplate.delete(FmsConstants.FILE_TOKEN_NAME_SPACE + uploadToken); + FmsFileUploadResult fmsFileUploadResult = new FmsFileUploadResult(); fmsFileUploadResult.setUniqueId(uniqueId); return CommonResult.success(fmsFileUploadResult); } + + /** + * 保存多个 + * 文件策略为NIO + * 执行文件写入和上传 + * + * @param files 文件 + * @param uploadToken 访问token + * @param uploadTokenParam 上传参数,文件的限制 + * @return + */ + @Override + public CommonResult> saveFileForNio(MultipartFile[] files, String uploadToken, FmsUploadTokenParam uploadTokenParam) { + + CommonResult> result = fmsFileSystemService.uploadFiles(files, uploadTokenParam); + //文件上传成功,删除文件访问的token + stringRedisTemplate.delete(FmsConstants.FILE_TOKEN_NAME_SPACE + uploadToken); + return result; + } + + /** + * 将文件持久化到数据库 + * + * @param file 文件 + * @param fmsUploadTokenParam 文件的类型等信息 + * @param uuid 文件唯一id + * @return + */ + @Override + public CommonResult createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid) { + String andPersistDBRecord = fmsFileSystemService.createAndPersistDBRecord(file, fmsUploadTokenParam, uuid); + return CommonResult.success(andPersistDBRecord); + } } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileHandleStrategyServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileHandleStrategyServiceImpl.java index a01bb3e..18f2d49 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileHandleStrategyServiceImpl.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileHandleStrategyServiceImpl.java @@ -1,25 +1,25 @@ package com.itools.core.service.impl; import com.itools.core.base.CommonResult; +import com.itools.core.bean.BeanCopyUtils; import com.itools.core.context.FileStrategyServiceContext; -import com.itools.core.em.FmsCodeBean; -import com.itools.core.em.FmsConstants; -import com.itools.core.exception.AppException; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.result.FmsBusinessTypeResult; import com.itools.core.result.FmsFileUploadResult; +import com.itools.core.result.FmsMultipartFileResult; import com.itools.core.result.FmsUploadTokenResult; import com.itools.core.service.FileHandleService; import com.itools.core.service.FmsFileHandleStrategyService; +import com.itools.core.service.FmsFileSystemService; import com.itools.core.system.AbstractService; -import com.itools.core.utils.StringUtils; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @project: itools-backend * @description: @@ -32,7 +32,8 @@ public class FmsFileHandleStrategyServiceImpl extends AbstractService implements private FileStrategyServiceContext fileStrategyServiceContext; @Autowired private FileHandleService fileHandleService; - + @Autowired + private FmsFileSystemService fmsFileSystemService; /** * 单个文件上传 @@ -46,33 +47,36 @@ public class FmsFileHandleStrategyServiceImpl extends AbstractService implements public CommonResult singletonUploadFile(MultipartFile file, String uploadToken) { //压缩过后的文件名称前端无法获取,额外的字段标识 String originalFilename = file.getOriginalFilename(); - //返回 - FmsFileUploadResult response = new FmsFileUploadResult(); //验证文件token CommonResult fmsUploadTokenResultCommonResult = fileHandleService.getFileDetailByToken(uploadToken); - FmsBusinessTypeResult businessType = fmsUploadTokenResultCommonResult.getData().getFsBusinessType(); - String fsSize = businessType.getFsSize(); - Long limitSize = Long.parseLong(fsSize); - long fileSize = file.getSize(); - int mult = 102400; - if (fileSize > (limitSize * mult)) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code); - } - String fsType = businessType.getFsType(); - if (!StringUtils.equals(fsType, FmsConstants.FILE_CURRENCY_TYPE)){ - String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); - String contentType = file.getContentType(); - if (contentType == null || !fsType.contains(suffix.trim().toLowerCase()) || !fsType.contains(contentType)) { - logger.error(FmsCodeBean.FmsCode.ERROR_FILETYPE.code, "文件类型:" + suffix + " || " + contentType); - // 文件后缀错误 - throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code); - } - } + FmsBusinessTypeResult businessType = fmsUploadTokenResultCommonResult.getData().getBusinessTypeResult(); + //验证文件 + fmsFileSystemService.verifyFiles(file,businessType); + FmsUploadTokenParam uploadTokenParam = new FmsUploadTokenParam(); + BeanCopyUtils.copyProperties(fmsUploadTokenResultCommonResult.getData(),uploadTokenParam); //执行文件上传,根据配置的不同策略处理文件上传 - CommonResult fmsFileUploadResultCommonResult = fileStrategyServiceContext.get().singletonUploadFiles(file, uploadToken, businessType, originalFilename); - response.setUniqueId(fmsFileUploadResultCommonResult.getData().getUniqueId()); + return fileStrategyServiceContext.get().singletonUploadFiles(file, uploadToken, uploadTokenParam, originalFilename); + } - return CommonResult.success(response); + /** + * 批量上传文件 + * @param files 文件 + * @param uploadToken 文件访问的token + * @return + */ + @Override + @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) + public CommonResult> filesMultipartUpload(MultipartFile[] files, String uploadToken) { + //验证文件token + CommonResult fmsUploadTokenResultCommonResult = fileHandleService.getFileDetailByToken(uploadToken); + + FmsBusinessTypeResult businessType = fmsUploadTokenResultCommonResult.getData().getBusinessTypeResult(); + //验证文件 + fmsFileSystemService.verifyFiles(files,businessType); + FmsUploadTokenParam uploadTokenParam = new FmsUploadTokenParam(); + BeanCopyUtils.copyProperties(fmsUploadTokenResultCommonResult.getData(),uploadTokenParam); + //执行文件上传,根据配置的不同策略处理文件上传 + return fileStrategyServiceContext.get().mutipartUploadFiles(files, uploadToken, uploadTokenParam); } } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java index 27eec26..ef9e454 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java @@ -15,11 +15,14 @@ import com.itools.core.mapper.FmsFileRecordMapper; import com.itools.core.param.FmsAccessTokenParam; import com.itools.core.param.FmsUploadTokenParam; import com.itools.core.param.FmsBusinessTypeParam; +import com.itools.core.request.FmsBase64FileUploadRequest; import com.itools.core.result.*; import com.itools.core.service.FmsFileSystemService; import com.itools.core.snowflake.SequenceService; +import com.itools.core.utils.Base64Utils; import com.itools.core.utils.CollectionUtils; import com.itools.core.utils.UUIDUtils; +import com.itools.core.utils.ZipUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,8 +36,11 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; +import sun.misc.BASE64Encoder; +import javax.servlet.http.HttpServletResponse; import java.io.*; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -151,7 +157,17 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { return createAndPersistDBRecord(file, fmsUploadTokenParam, uuid); } - protected String createAndPersistDBRecord(String originalFilename, String contentType, Long fileSize, FmsUploadTokenParam fmsUploadTokenParam, String fileUnqieId) { + /** + * 文件持久化到数据库 + * @param originalFilename + * @param contentType + * @param fileSize + * @param fmsUploadTokenParam + * @param fileUnqieId + * @return + */ + @Transactional(rollbackFor = Exception.class) + public String createAndPersistDBRecord(String originalFilename, String contentType, Long fileSize, FmsUploadTokenParam fmsUploadTokenParam, String fileUnqieId) { FmsRecordDTO fssRecord = new FmsRecordDTO(); Date date = new Date(); fssRecord.setId(sequenceService.nextValue(FmsConstants.FSS_RECORD_ID_SEQ_NAME)); @@ -163,13 +179,19 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { fssRecord.setOrigFileName(originalFilename); fssRecord.setCreateTime(date); fssRecord.setUpdateTime(date); - if (fmsFileRecordMapper.insertSelective(fssRecord) == 1) { - return fileUnqieId; - } - throw new AppException(FmsCodeBean.FmsCode.FAIL.code); - } + fmsFileRecordMapper.insertSelective(fssRecord); + return fileUnqieId; + } - protected String createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid) { + /** + * 文件持久化到数据库 + * @param file + * @param fmsUploadTokenParam + * @param uuid + * @return + */ + @Override + public String createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid) { String originalFilename = file.getOriginalFilename(); if (!StringUtils.isBlank(fmsUploadTokenParam.getOriginalFilename())){ originalFilename = fmsUploadTokenParam.getOriginalFilename(); @@ -248,7 +270,7 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { } FmsUploadTokenParam fsUploadToken = new FmsUploadTokenParam(); fsUploadToken.setFromSystemId(fromSystemId); - fsUploadToken.setFsBusinessType(fsBusinessTypes.get(0)); + fsUploadToken.setBusinessTypeResult(fsBusinessTypes.get(0)); fsUploadToken.setNeedEncrypt(needEncrypt); fsUploadToken.setRemark(remark); //将文件申请的token写入到缓存 @@ -258,7 +280,6 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { } catch (JsonProcessingException e) { logger.error("JackJson序列化失败"); } -// fmsBusinessTypeService.cacheFsUploadToken(uploadToken, fsUploadToken); return CommonResult.success(uploadToken); } @@ -313,45 +334,45 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { */ @Override @Logable - public String getFileUrlByFileId(String uniqueId, int expiredTime, int maxAccessCount, String type) { + public CommonResult getFileUrlByFileId(String uniqueId, int expiredTime, int maxAccessCount, String type) { FmsRecordDTO tmp = new FmsRecordDTO(); tmp.setUniqueId(uniqueId); List fsUploadRecords = fmsFileRecordMapper.selectbySelective(tmp); if (fsUploadRecords == null || fsUploadRecords.isEmpty()) { logger.error(FmsCodeBean.FmsCode.NOT_EXIST_FILE.message,new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code, FmsCodeBean.FmsCode.NOT_EXIST_FILE.message)); - return ""; + return CommonResult.success(null); } String fileAccessToken = UUIDUtils.uuid(); - //String fileAccessUrlForOutter = "http://192.168.0.135:8150/fs/File/";//本地路径 + //String fileAccessUrlForOutter = "http://192.168.0.135:8150/fms/File/";//本地路径 String path = fileAccessUrlForOutter + uniqueId + "?fileAccessToken=" + fileAccessToken; // 缓存文件token FmsAccessTokenResult fsAccessToken = fmsAccessTokenService.cacheFileAccessToken(fileAccessToken, expiredTime, maxAccessCount, uniqueId, type); if (fsAccessToken == null) { throw new AppException(FmsCodeBean.FmsCode.FAIL.code); } - return path; + return CommonResult.success(path); } /** * 获得uniqueId对应的文件上传记录 * 会检查 - * @param fsAccessToken + * @param accessTokenParam * @param uniqueId * @param fileAccessToken * @return */ @Override @Logable - public FmsDetailRecordResult getFileUploadRecord(FmsAccessTokenParam fsAccessToken, String uniqueId, String fileAccessToken) { + public FmsDetailRecordResult getFileUploadRecord(FmsAccessTokenParam accessTokenParam, String uniqueId, String fileAccessToken) { FmsRecordDTO tmp = new FmsRecordDTO(); tmp.setUniqueId(uniqueId); - List fsUploadRecords = fmsFileRecordMapper.selectbySelective(tmp); - if (fsUploadRecords == null || fsUploadRecords.isEmpty()) { + List uploadRecords = fmsFileRecordMapper.selectbySelective(tmp); + if (uploadRecords == null || uploadRecords.isEmpty()) { // 无该文件,返回404 throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code); } - int maxAccessCount = fsAccessToken.getMaxAccessCount(); - if (fsAccessToken.getExpiredTime() > 0){ + int maxAccessCount = accessTokenParam.getMaxAccessCount(); + if (accessTokenParam.getExpiredTime() > 0){ if (maxAccessCount != -1) { // 次数减一 maxAccessCount--; @@ -360,8 +381,8 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { fmsAccessTokenService.deleteFileAccessToken(fileAccessToken); } else { // 更新缓存 - int expiredTime = fsAccessToken.getExpiredTime(); - fmsAccessTokenService.cacheFileAccessToken(fileAccessToken, expiredTime, maxAccessCount, uniqueId, fsAccessToken.getType()); + int expiredTime = accessTokenParam.getExpiredTime(); + fmsAccessTokenService.cacheFileAccessToken(fileAccessToken, expiredTime, maxAccessCount, uniqueId, accessTokenParam.getType()); // 更新缓存时间 redisTemplate.expire(fileAccessToken, expiredTime, TimeUnit.MINUTES); } @@ -369,7 +390,7 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { } // 返回该文件 - FmsRecordDTO fssRecord = fsUploadRecords.get(0); + FmsRecordDTO fssRecord = uploadRecords.get(0); FmsDetailRecordResult result = new FmsDetailRecordResult(); BeanUtils.copyProperties(fssRecord , result); return result; @@ -393,20 +414,19 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { /** * 文件批量上传 * @param files - * @param param + * @param fmsUploadTokenParam * @return */ @Override - public CommonResult uploadFiles(MultipartFile[] files, FmsUploadTokenParam param) { + public CommonResult> uploadFiles(MultipartFile[] files, FmsUploadTokenParam fmsUploadTokenParam) { //收集文件数对应的结果 List results = new ArrayList<>(); List> taskList = new ArrayList<>(); for (MultipartFile file : files){ //执行多线程上传 执行上传的service,文件,参数 -// this.saveFile(file,param); String uuid = UUIDUtils.uuid(); - FutureTask futureTask = new FutureTask<>(new FmsFileRecordUploadTask(self,file,param,uuid)); + FutureTask futureTask = new FutureTask<>(new FmsFileRecordUploadTask(self,file,fmsUploadTokenParam,uuid)); taskList.add(futureTask); //返回信息 FmsMultipartFileResult multipartFileResult = new FmsMultipartFileResult(); @@ -485,35 +505,22 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code); } } - /** - * 文件批量上传的业务逻辑 - * @param files - * @param uploadToken - * @return + * 验证文件 + * @param multipartFile + * @param fsBusinessType */ @Override - @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) - public CommonResult filesMultipartUpload(MultipartFile[] files, String uploadToken) { - //验证token是否合理 - FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(uploadToken); - if (fsUploadToken == null) { - throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code); + public void verifyFiles(MultipartFile multipartFile, FmsBusinessTypeResult fsBusinessType) { + if (multipartFile == null){ + throw new AppException(FmsCodeBean.FmsCode.ERROR_FILE_IS_NULL.code); } - //获取文件允许是类型 - FmsBusinessTypeResult fsBusinessType = fsUploadToken.getFsBusinessType(); - //验证文件 - self.verifyFiles(files,fsBusinessType); - FmsUploadTokenParam param = new FmsUploadTokenParam(); - BeanUtils.copyProperties(fsUploadToken , param); - //批量上传 - CommonResult fileResult = self.uploadFiles(files,param); -// String uniqueId = fsService.saveFile(file, param); - //删除token - fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(uploadToken); - return CommonResult.success(fileResult.getData()); + MultipartFile[] multipartFiles = new MultipartFile[1]; + multipartFiles[0] = multipartFile; + this.verifyFiles(multipartFiles,fsBusinessType); } + /** * 获取文件访问路径,如果超时时间设置为小于等于0,那么返回的有效路径可以永久访问 * @param uniqueIds @@ -524,7 +531,7 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { */ @Override @Transactional(propagation = Propagation.SUPPORTS,readOnly = true,rollbackFor = Exception.class) - public CommonResult getFileUrlByFileIds(List uniqueIds, Integer expiredTime, int maxAccessCount, String type) { + public CommonResult> getFileUrlByFileIds(List uniqueIds, Integer expiredTime, int maxAccessCount, String type) { if (CollectionUtils.isEmpty(uniqueIds)){ logger.error(FmsCodeBean.FmsCode.NOT_EXIST_FILE.message,new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code, FmsCodeBean.FmsCode.NOT_EXIST_FILE.message)); @@ -574,5 +581,143 @@ public class FmsFileSystemServiceImpl implements FmsFileSystemService { return CommonResult.success(recordPathResults); } + /** + * 下载文件 + * @param fileAccessToken + * @param response + * @param uniqueId + */ + @Override + public void downloadFile(String fileAccessToken, HttpServletResponse response, String uniqueId) { + try { + FmsAccessTokenResult accessToken = fmsAccessTokenService.getFileAccessToken(fileAccessToken); + if (accessToken == null) { + throw new AppException(FmsCodeBean.FmsCode.INVALID_FS_TOKEN.code); + } + if (!uniqueId.equals(accessToken.getUniqueId())) { + throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code); + } + FmsAccessTokenParam param = new FmsAccessTokenParam(); + BeanUtils.copyProperties(accessToken , param); + //获得uniqueId对应的文件上传记录 + FmsDetailRecordResult fsUploadRecord = this.getFileUploadRecord(param, uniqueId, fileAccessToken); + String type = accessToken.getType(); + if (FmsConstants.SHOW.equals(type)) { + response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize()); + } else if (FmsConstants.DOWNLOAD.equals(type)) { + // 设置文件名, 可用于下载 + response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize()); + response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fsUploadRecord.getOrigFileName(), "utf-8")); + } + response.setCharacterEncoding("UTF-8"); + response.setContentType(fsUploadRecord.getContentType()); + OutputStream outputStream = response.getOutputStream(); + //根据uniqeId和文件名得到本地文件存储路径 + FileCopyUtils.copy(new FileInputStream(this.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName())), outputStream); + } catch (AppException e) { + String errorCode = e.getErrorCode(); + response.setStatus(Integer.parseInt(errorCode)); + return; + } catch (IOException e) { + response.setStatus(500); + return; + } + } + + /** + * 获取base64文件 + * + * @param uniqueId + * @return + */ + @Override + public CommonResult getFileBase64(String uniqueId) { + FmsDetailRecordResult fsUploadRecord = this.getFileUploadRecord(uniqueId); + try { + String path = this.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName()); + File file = new File(path); + FileInputStream fileInputStream = new FileInputStream(file); + byte[] buffer = new byte[(int)file.length()]; + fileInputStream.read(buffer); + fileInputStream.close(); + return CommonResult.success(new BASE64Encoder().encode(buffer)); + } catch (Exception e) { + logger.error(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, e); + throw new AppException(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.message); + } + } + + /** + * 上传base64文件 + * + * @param base64Req + * @return + */ + @Override + public CommonResult uploadFileBase64(FmsBase64FileUploadRequest base64Req) { + FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(base64Req.getUploadToken()); + if (fsUploadToken == null) { + throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code); + } + FmsBusinessTypeResult fsBusinessType = fsUploadToken.getBusinessTypeResult(); + byte[] fileBytes; + try { + //将字符串转换为byte数组 + fileBytes = Base64Utils.decode(base64Req.getFileBaseSixFour()); + } catch (Exception e) { + throw new AppException(FmsCodeBean.FmsCode.FAIL.code); + } + + String fsSize = fsBusinessType.getFsSize(); + Long limitSize = Long.parseLong(fsSize); + long fileSize = fileBytes.length; + int mult = 1024; + if (fileSize > (limitSize * mult)) { + throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code); + } + if (!fsBusinessType.getBusinessType().equals(base64Req.getBusinessType())) { + // 文件类型不一致 + throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code); + } + FmsBusinessTypeParam fmsBusinessTypeParam = new FmsBusinessTypeParam(); + BeanUtils.copyProperties(fsBusinessType , fmsBusinessTypeParam); + FmsUploadTokenParam fmsUploadTokenParam = new FmsUploadTokenParam(); + BeanUtils.copyProperties(fsUploadToken , fmsUploadTokenParam); + String fileUploadResponse = this.saveFileFromBytes(fileBytes, base64Req.getFileName(), fmsBusinessTypeParam, fmsUploadTokenParam); + fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(base64Req.getUploadToken()); + return CommonResult.success(fileUploadResponse); + } + + /** + * 下载zip压缩文件接口 + * @param uniqueIds + * @param zipName + * @param response + */ + @Override + public void downloadZipByUniqueIds(List uniqueIds, String zipName, HttpServletResponse response) { + if (com.itools.core.utils.StringUtils.isBlank(zipName)) { + zipName = "attachment"; + } + List paths = new ArrayList<>(); + List files = new ArrayList<>(); + for (String uniqueId : uniqueIds) { + FmsDetailRecordResult fsUploadRecord = this.getFileUploadRecord(uniqueId); + String path = this.getFileLocalPath(uniqueId, fsUploadRecord.getOrigFileName()); + paths.add(path); + File file = new File(path); + files.add(file); + } + try { + response.setContentType("application/zip"); + response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(zipName + ".zip", "utf-8")); + OutputStream outputStream = response.getOutputStream(); + ZipUtils.toZip(files, outputStream); + } catch (FileNotFoundException e) { + throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsRecordServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsRecordServiceImpl.java index a2d8f7c..d45e8a1 100644 --- a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsRecordServiceImpl.java +++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsRecordServiceImpl.java @@ -1,9 +1,11 @@ package com.itools.core.service.impl; +import com.itools.core.base.CommonResult; import com.itools.core.dto.fileRecord.FmsRecordDTO; import com.itools.core.mapper.FmsFileRecordMapper; import com.itools.core.result.FmsDetailRecordResult; import com.itools.core.service.FmsRecordService; +import com.itools.core.utils.CollectionUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -19,19 +21,24 @@ public class FmsRecordServiceImpl implements FmsRecordService { @Autowired private FmsFileRecordMapper fmsFileRecordMapper; - + + /** + * 查询文件记录 + * @param uniqueId 文件唯一id + * @return + */ @Override - public FmsDetailRecordResult queryFssRecordByUniqueId(String uniqueId) { + public CommonResult queryFssRecordByUniqueId(String uniqueId) { FmsRecordDTO queryParams = new FmsRecordDTO(); queryParams.setUniqueId(uniqueId); - List list = fmsFileRecordMapper.selectbySelective(queryParams); - if (list.size() > 0) { - FmsRecordDTO record = list.get(0); + List recordDTOS = fmsFileRecordMapper.selectbySelective(queryParams); + if (!CollectionUtils.isEmpty(recordDTOS)) { + FmsRecordDTO record = recordDTOS.get(0); FmsDetailRecordResult result = new FmsDetailRecordResult(); BeanUtils.copyProperties(record , result); - return result; + return CommonResult.success(result); } - return null; + return CommonResult.success(null); } } diff --git a/itools-fms/itools-fms-server/src/main/resources/application-dev.yml b/itools-fms/itools-fms-server/src/main/resources/application-dev.yml index 6dffb75..933c2ae 100644 --- a/itools-fms/itools-fms-server/src/main/resources/application-dev.yml +++ b/itools-fms/itools-fms-server/src/main/resources/application-dev.yml @@ -16,33 +16,27 @@ spring: # 最大支持请求大小 max-request-size: 200MB # 上传文件的临时目录 -# location: /home/hash/AppSvr01/installedApps/fsnsh_backend-master/temp - - -fileStoreRootPath: /data/fmsFile #文件存储路径,此路径应该是多个FSS服务的共享磁盘 -fileAccessUrlForOutter: http://127.0.0.1:8002/File/ -fileUploadLimitSize: 10 #批量上传限制的个数 -fileMaxRequestSize: 204800 #最大的请求数,单位KB,200MB -fileMaxFileSize: 20480 #单个文件最大大小,单位KB,20MB + enabled: true +# location: /data/fmsFile/temp fms: - #系统文件管理策略【nio原生的文件系统,miniio文件系统,fastdfs文件系统】 - strategy: nio + #系统文件管理策略【nio原生的文件系统,minio文件系统,fastdfs文件系统】 + strategy: minio #文件的token的过期时间单位分钟 token-expiration-time: 5 #文件配置 file: - store-root-path: /data/fmsFile #文件存储路径,此路径应该是多个fms服务的共享磁盘 - access-url-for-outter: http://127.0.0.1:8002/File/ #文件访问 + store-root-path: fmsfile #文件存储路径,此路径应该是多个fms服务的共享磁盘 + access-url-for-outter: http://127.0.0.1:8002/get/file/ #文件访问 upload-limit-size: 10 #批量上传限制的个数 max-request-size: 204800 #最大的请求数,单位KB,200MB max-file-size: 20480 #单个文件最大大小,单位KB,20MB #minio文件配置 minio: - endpoint: 172.28.43.29 + endpoint: 127.0.0.1 port: 9000 - accessKey: minio - secretKey: miniopassword + accessKey: minioadmin + secretKey: minioadmin secure: false bucketName: "hope-bucket" configDir: "/home/data/" -- Gitee