diff --git a/doc/sql/ddl/20210716_oss_init.sql b/doc/sql/ddl/20210716_oss_init.sql index 78c405b..f6fe324 100644 --- a/doc/sql/ddl/20210716_oss_init.sql +++ b/doc/sql/ddl/20210716_oss_init.sql @@ -120,7 +120,7 @@ CREATE TABLE `file` ( `is_delete` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否逻辑删除(0:未删除,1:已删除)', PRIMARY KEY (`id`), INDEX idx_create_at(create_at), + INDEX idx_url_md5_app_code(url_md5, app_code), UNIQUE KEY uk_file_uuid(`file_uuid`), - UNIQUE KEY uk_file_md5(`file_uuid`), UNIQUE KEY idx_app_code_bucket_name_file_url(`app_channel_bucket_no`, `directory`, `file_uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件上传记录'; \ No newline at end of file diff --git a/doc/sql/dml/oss_data_init.sql b/doc/sql/dml/oss_data_init.sql new file mode 100644 index 0000000..19c5b41 --- /dev/null +++ b/doc/sql/dml/oss_data_init.sql @@ -0,0 +1,14 @@ +INSERT INTO `app_channel_bucket`( `app_channel_bucket_no`, `app_code`, `channel_code`, `bucket_name`) +VALUES ( 'zeus:aliyun:zeus', 'zeus', 'aliyun', 'axzo-oss'); + +INSERT INTO `file_app`(`app_code`, `app_name`, `status`, `remark` ) +VALUES ('zeus', 'zeus', 1, 'zeus'); + +INSERT INTO `file_business_scene`(`app_channel_bucket_no`, `app_code`, `channel_code`, `bucket_name`, `business_scene`, `directory`) +VALUES ('zeus:aliyun:zeus', 'zeus', 'aliyun', 'axzo-oss', 'recruit_collect', 'zeus/recruit_collect'); + +INSERT INTO `file_channel`(`channel_code`, `channel_name`, `status`, `priority`) +VALUES ('aliyun', '阿里云', 1, 1); + +INSERT INTO `file_upload_config`(`app_channel_bucket_no`, `app_code`, `channel_code`, `bucket_name`, `directory`, `storage_unit`, `storage_size`, `file_format`) +VALUES ('zeus:aliyun:zeus', 'zeus', 'aliyun', 'axzo-oss', 'zeus/recruit_collect', 'MB', 5, 'xlsx'); \ No newline at end of file diff --git a/oss-client/pom.xml b/oss-client/pom.xml index ee16508..cfee4f0 100644 --- a/oss-client/pom.xml +++ b/oss-client/pom.xml @@ -106,6 +106,14 @@ 1.8 + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + diff --git a/oss-client/src/main/java/cn/axzo/oss/client/Bootstrap.java b/oss-client/src/main/java/cn/axzo/oss/client/Bootstrap.java index d82dbe1..9c62c48 100644 --- a/oss-client/src/main/java/cn/axzo/oss/client/Bootstrap.java +++ b/oss-client/src/main/java/cn/axzo/oss/client/Bootstrap.java @@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @Slf4j @MapperScan(basePackages = {"cn.axzo.oss.dal.mapper"}) @SpringBootApplication(scanBasePackages = {"cn.axzo.oss"}) +@MapperScan(basePackages = {"cn.axzo.oss.dal.mapper"}) public class Bootstrap { public static void main(String[] args) { diff --git a/oss-client/src/main/java/cn/axzo/oss/client/annotation/resolver/ApiAccessCheckResolver.java b/oss-client/src/main/java/cn/axzo/oss/client/annotation/resolver/ApiAccessCheckResolver.java new file mode 100644 index 0000000..13dfa08 --- /dev/null +++ b/oss-client/src/main/java/cn/axzo/oss/client/annotation/resolver/ApiAccessCheckResolver.java @@ -0,0 +1,35 @@ +package cn.axzo.oss.client.annotation.resolver; + +import cn.axzo.oss.common.annotation.ApiAccessCheck; +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * @program: oss + * @description: 访问校验实现 + * @author: mr.jie + * @date: 2021-07-28 01:23 + **/ +@Aspect +@Component +@Slf4j +public class ApiAccessCheckResolver { + + @Around("@annotation(apiAccessCheck)") + public Object methodHandler(ProceedingJoinPoint jp, ApiAccessCheck apiAccessCheck) + throws Throwable { + Object[] params = jp.getArgs(); + log.info("methodHandler params = {}", JSONObject.toJSON(params)); + Object result = jp.proceed(); + return result; + } + +} diff --git a/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java b/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java index 75b4309..de4859d 100644 --- a/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java +++ b/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java @@ -1,10 +1,15 @@ package cn.axzo.oss.client.controller; +import cn.axzo.oss.common.utils.BeanConvertUtil; import cn.axzo.oss.http.api.ServerFileServiceApi; import cn.axzo.oss.http.model.ServerFileDeleteRequest; import cn.axzo.oss.http.model.ServerFileUploadRequest; import cn.axzo.oss.http.model.ServerFileUploadResponse; +import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto; +import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto; +import cn.axzo.oss.service.api.FileService; import cn.azxo.framework.common.model.CommonResponse; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -20,13 +25,25 @@ import javax.validation.Valid; @RestController public class ServerFileController implements ServerFileServiceApi { - @Override - public CommonResponse upload(@Valid @RequestBody ServerFileUploadRequest request) { - return null; - } + @Autowired + private FileService fileService; + @Override + public CommonResponse upload(@Valid @RequestBody ServerFileUploadRequest request) { + ServerFileUploadDto dto = BeanConvertUtil.copyBean(request, ServerFileUploadDto.class); + request.setFileContent(null); + return CommonResponse.success(fileService.upload(dto)); + } + + /** + * 根据文件url删除文件 + * @param request + * @return + */ @Override public CommonResponse delete(@Valid @RequestBody ServerFileDeleteRequest request) { - return null; + ServerFileDeleteDto dto = BeanConvertUtil.copyBean(request, ServerFileDeleteDto.class); + fileService.delete(dto); + return CommonResponse.success(); } } diff --git a/oss-client/src/main/java/cn/axzo/oss/client/handler/ControllerExceptionHandler.java b/oss-client/src/main/java/cn/axzo/oss/client/handler/ControllerExceptionHandler.java new file mode 100644 index 0000000..ceb8e78 --- /dev/null +++ b/oss-client/src/main/java/cn/axzo/oss/client/handler/ControllerExceptionHandler.java @@ -0,0 +1,74 @@ +package cn.axzo.oss.client.handler; + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.common.exception.S3Exception; +import cn.azxo.framework.common.model.CommonResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * @program: oss + * @description: 全局异常捕捉 + * @author: mr.jie + * @date: 2021-07-29 19:51 + **/ +@Slf4j +@RestControllerAdvice +public class ControllerExceptionHandler { + + @ExceptionHandler(value = BizException.class) + public CommonResponse bizException(BizException e){ + log.warn("[oss] ControllerExceptionHandler.bizException Exception", e); + return CommonResponse.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(value = S3Exception.class) + public CommonResponse bizException(S3Exception e){ + log.warn("[oss] ControllerExceptionHandler.s3Exception Exception", e); + return CommonResponse.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(value = IllegalArgumentException.class) + public CommonResponse handleIllegalArgumentException(IllegalArgumentException e) { + log.error("[oss] ControllerExceptionHandler.handleIllegalArgumentException Exception message ", e); + return CommonResponse.error(CodeEnum.INVALID_PARAMETER.getCode(), e.getMessage()); + } + + @ExceptionHandler(value = DuplicateKeyException.class) + public CommonResponse handleDuplicateKeyException(DuplicateKeyException e) { + log.error("[oss] ControllerExceptionHandler.handleDuplicateKeyException Exception message ", e); + return CommonResponse.error(CodeEnum.REPEATED_REQUEST.getCode(), e.getCause().getMessage()); + } + + @ExceptionHandler(value = Exception.class) + public CommonResponse handleOtherException(Exception e) { + log.error("[oss] ControllerExceptionHandler.handleOtherException Exception", e); + return CommonResponse.error(CodeEnum.SYSTEM_ERROR.getCode(), CodeEnum.SYSTEM_ERROR.getMessage()); + } + + @ExceptionHandler(value = Throwable.class) + public CommonResponse handleThrowableException(Throwable e) { + log.error("[oss] ControllerExceptionHandler.handleThrowableException Exception", e); + return CommonResponse.error(CodeEnum.SYSTEM_ERROR.getCode(), CodeEnum.SYSTEM_ERROR.getMessage()); + } + + @ExceptionHandler(value = MethodArgumentNotValidException.class) + public CommonResponse handleArgumentValidException(MethodArgumentNotValidException e){ + log.warn("[oss] ControllerExceptionHandler.handleArgumentValidException Exception", e.getMessage()); + BindingResult bindingResult = e.getBindingResult(); + StringBuilder errorMsg = new StringBuilder(); + for (FieldError fieldError : bindingResult.getFieldErrors()) { + if (-1 == errorMsg.indexOf(fieldError.getDefaultMessage())) { + errorMsg.append(fieldError.getDefaultMessage()).append(","); + } + } + errorMsg.deleteCharAt(errorMsg.length() - 1); + return CommonResponse.error(CodeEnum.INVALID_PARAMETER.getCode(), errorMsg.toString()); + } +} diff --git a/oss-common/pom.xml b/oss-common/pom.xml index 07e736d..9d994ed 100644 --- a/oss-common/pom.xml +++ b/oss-common/pom.xml @@ -5,7 +5,7 @@ cn.axzo.oss oss - 1.0.0 + ${revision} oss-common @@ -70,6 +70,10 @@ org.projectlombok lombok + + commons-codec + commons-codec + diff --git a/oss-common/src/main/java/cn/axzo/oss/common/annotation/ApiAccessCheck.java b/oss-common/src/main/java/cn/axzo/oss/common/annotation/ApiAccessCheck.java new file mode 100644 index 0000000..7a72345 --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/annotation/ApiAccessCheck.java @@ -0,0 +1,18 @@ +package cn.axzo.oss.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @program: oss + * @description: 访问校验 + * @author: mr.jie + * @date: 2021-07-28 00:50 + **/ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ApiAccessCheck { + +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/constans/CommonConstants.java b/oss-common/src/main/java/cn/axzo/oss/common/constans/CommonConstants.java index 5563e0a..a8e2922 100644 --- a/oss-common/src/main/java/cn/axzo/oss/common/constans/CommonConstants.java +++ b/oss-common/src/main/java/cn/axzo/oss/common/constans/CommonConstants.java @@ -8,4 +8,56 @@ package cn.axzo.oss.common.constans; * @since 2021-07-15 11:45 */ public abstract class CommonConstants { + + /** + * 在指定字符串未找字符串的位置 + */ + public static final int NOT_FOUND_INDEX_OF = -1; + /** + * 1 + */ + public static final int ONE = 1; + + + + /** + * 是否删除 + */ + public interface TableDelete { + + /** + * 未删除 + */ + Integer UN_DELETED = 0; + /** + * 已删除 + */ + Integer DELETED = 1; + } + + /** + * 文件状态 + */ + public interface FileStatus { + + /** + * 处理中 + */ + Integer PROCESSING = 0; + + /** + * 上传成功 + */ + Integer SUCCESS = 1; + + /** + * 上传失败 + */ + Integer FAIL = 2; + + /** + * 已删除 + */ + Integer DELETED = 3; + } } diff --git a/oss-common/src/main/java/cn/axzo/oss/common/enums/CodeEnum.java b/oss-common/src/main/java/cn/axzo/oss/common/enums/CodeEnum.java new file mode 100644 index 0000000..e8323bc --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/enums/CodeEnum.java @@ -0,0 +1,50 @@ +package cn.axzo.oss.common.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 系统返回码枚举类 + * + * @author zhaoyong_sh + * @see CodeEnum + * @since 2021-05-17 15:57 + */ +@RequiredArgsConstructor +@Getter +public enum CodeEnum implements EnumBase { + + /** + * 系统返回码枚举类 + */ + SUCCESS(200, "success"), + SYSTEM_ERROR(500, "system error"), + FAIL(400, "service exception"), + + /** + * 0-100 系统相关 错误码 + */ + INVALID_PARAMETER(1, "无效的参数"), + REPEATED_REQUEST(2, "重复的请求"), + + /** + * 101-200 业务场景 + */ + S3_CLIENT_NULL(101,"oss client is null"), + APP_CODE_NOT_FOUND(102,"app code not found"), + APP_CHANNEL_BUCKET_NOT_FOUND(103,"channel bucket not found"), + APP_CHANNEL_NOT_FOUND(104,"channel not found"), + NO_CHANNELS_AVAILABLE(105,"no channels available"), + NO_UPLOAD_CONFIG(106,"no upload config"), + FILE_SIZE_EXCEEDS_LIMIT(107,"file size exceeds limit"), + NOT_FILE_FORMAT(108,"failed to get file format"), + FILE_FORMAT_NOT_SUPPORTED(109,"file format is not supported"), + FILE_UPLOAD_FAILED(109,"file upload failed"), + + ; + + private final Integer code; + + private final String message; + +} \ No newline at end of file diff --git a/oss-common/src/main/java/cn/axzo/oss/common/enums/FileClassEnum.java b/oss-common/src/main/java/cn/axzo/oss/common/enums/FileClassEnum.java new file mode 100644 index 0000000..6aa37e9 --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/enums/FileClassEnum.java @@ -0,0 +1,27 @@ +package cn.axzo.oss.common.enums; + +/** + * @author: zhangran + * @date: 20210805 21:31 + * @description: 文件类符号 + **/ +public enum FileClassEnum { + + + SEPARATOR_CHAR("/", "默认 分割器"), + DOT(".", "文件命后缀 如abc.xlsx"), + COMMA(",", "逗号"), + ; + + + FileClassEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + + public final String type; + + public final String desc; + +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/enums/FileStatusEnum.java b/oss-common/src/main/java/cn/axzo/oss/common/enums/FileStatusEnum.java new file mode 100644 index 0000000..fcf005d --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/enums/FileStatusEnum.java @@ -0,0 +1,35 @@ +package cn.axzo.oss.common.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * @author: zhangran + * @date: 20210802 14:48 + * @description: + **/ +@Getter +@RequiredArgsConstructor +public enum FileStatusEnum implements EnumBase { + /** + * 处理中 + */ + STATUS_PROCESSING(0, "处理中"), + /** + * 上传成功 + */ + STATUS_UPLOAD_SUCCESS(1, "上传成功"), + /** + * 上传失败 + */ + STATUS_UPLOAD_FAIL(2, "上传失败"), + /** + * 已删除 + */ + STATUS_DELETE(3, "已删除"), + ; + + private final Integer code; + + private final String message; +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/enums/StorageUnitEnum.java b/oss-common/src/main/java/cn/axzo/oss/common/enums/StorageUnitEnum.java new file mode 100644 index 0000000..cedcbca --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/enums/StorageUnitEnum.java @@ -0,0 +1,43 @@ +package cn.axzo.oss.common.enums; + +import java.util.Arrays; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * @ClassName: cn.axzo.oss.common.enums + * @description: + * @author: + * @date: 2021/8/119:04 + **/ +@Getter +@RequiredArgsConstructor +public enum StorageUnitEnum { + + /** + * B + */ + B(1, "B"), + /** + * KB + */ + KB(B.size * 1024, "KB"), + /** + * MB + */ + MB(KB.size * 1024, "MB"), + /** + * GB + */ + GB(MB.size * 1024, "GB"), + ; + + + private final Integer size; + private final String unit; + + public static StorageUnitEnum value(String unit) { + return Arrays.stream(values()).filter(storageUnitEnum -> storageUnitEnum.getUnit().equals(unit)) + .findFirst().orElse(null); + } +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/exception/BizException.java b/oss-common/src/main/java/cn/axzo/oss/common/exception/BizException.java new file mode 100644 index 0000000..1513c64 --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/exception/BizException.java @@ -0,0 +1,97 @@ +package cn.axzo.oss.common.exception; + +import cn.axzo.oss.common.enums.CodeEnum; +import lombok.Getter; +import lombok.Setter; +import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; + +/** + * 业务异常 + * + * @author zhaoyong_sh + * @see BizException + * @since 2021-05-17 15:56 + */ +@Getter +@Setter +public class BizException extends RuntimeException { + + private Integer code; + + private String message; + + /** + * 需返回的业务数据 + */ + private Object data; + + public BizException(Integer code) { + this.code = code; + } + + public BizException(CodeEnum returnCode) { + super(returnCode.getMessage()); + this.code = returnCode.getCode(); + this.message = returnCode.getMessage(); + } + + public BizException(CodeEnum returnCode, String message) { + super(returnCode.getMessage()); + this.code = returnCode.getCode(); + this.message = message; + } + + public BizException(Integer code, Throwable cause) { + super(null, cause); + this.code = code; + } + + public BizException(Integer code, String message, Object data) { + super(message); + this.code = code; + this.message = message; + this.data = data; + } + + public BizException(Integer code, String message, Object data, Throwable cause) { + super(message, cause); + this.code = code; + this.message = message; + this.data = data; + } + + public static void error(boolean b, CodeEnum returnCode) { + if (!b) { + throw new BizException(returnCode.getCode(), returnCode.getMessage(), null); + } + } + + public static void error(boolean b, CodeEnum returnCode, String message) { + if (!b) { + throw new BizException(returnCode.getCode(), message, null); + } + } + + public static void error(boolean b, Integer code, String message) { + if (!b) { + throw new BizException(code, message, null); + } + } + + public static void error(boolean b, Integer code, String message, Object data) { + if (!b) { + throw new BizException(code, message, data); + } + } + + public static void error(CodeEnum returnCode) { + throw new BizException(returnCode.getCode(), returnCode.getMessage(), null); + } + + public static void isEmpty(@Nullable Object obj, CodeEnum returnCode) { + if (ObjectUtils.isEmpty(obj)) { + throw new BizException(returnCode.getCode(), returnCode.getMessage(), null); + } + } +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/exception/S3Exception.java b/oss-common/src/main/java/cn/axzo/oss/common/exception/S3Exception.java new file mode 100644 index 0000000..5593e15 --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/exception/S3Exception.java @@ -0,0 +1,43 @@ +package cn.axzo.oss.common.exception; + +/** + * @program: oss + * @description: 文件上传异常 + * @author: mr.jie + * @date: 2021-07-29 19:28 + **/ +public class S3Exception extends RuntimeException { + + private Integer code; + + private String msg; + + public S3Exception(Integer code, String msg) { + this.code = code; + this.msg = msg; + } + + public void setCode(Integer code) { + this.code = code; + } + + public Integer getCode() { + return code; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String getMsg() { + return msg; + } + + @Override + public String toString() { + return "S3Exception{" + + "code=" + code + + ", msg='" + msg + '\'' + + '}'; + } +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/utils/BeanConvertUtil.java b/oss-common/src/main/java/cn/axzo/oss/common/utils/BeanConvertUtil.java new file mode 100644 index 0000000..32a54cd --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/utils/BeanConvertUtil.java @@ -0,0 +1,28 @@ +package cn.axzo.oss.common.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:53 + * @Version 0.0.1 + **/ +@Slf4j +public class BeanConvertUtil { + + public static T copyBean(Object source, Class targetCls) { + T target = null; + if (Utility.objIsNotNull(source)) { + try { + target = BeanUtils.instantiateClass(targetCls); + BeanUtils.copyProperties(source, target); + } catch (BeansException e) { + log.warn("copyBean error, e = {}", e); + } + } + return target; + } +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java b/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java new file mode 100644 index 0000000..f834e39 --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java @@ -0,0 +1,21 @@ +package cn.axzo.oss.common.utils; + +import com.alibaba.fastjson.JSONObject; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 23:37 + * @Version 0.0.1 + **/ +public class JsonUtil { + + /** + * 对象转json字符串 + * @param obj + * @return + */ + public static String obj2Str(Object obj){ + return JSONObject.toJSONString(obj); + } +} diff --git a/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java b/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java new file mode 100644 index 0000000..db15d6c --- /dev/null +++ b/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java @@ -0,0 +1,128 @@ +package cn.axzo.oss.common.utils; + +import cn.axzo.oss.common.enums.FileClassEnum; +import cn.axzo.oss.common.enums.StorageUnitEnum; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Objects; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:54 + * @Version 0.0.1 + **/ + +@Slf4j +public class Utility { + + + /** + * 判断对象为null + * @param obj + * @return + */ + public static boolean objIsNull(Object obj){ + return Objects.isNull(obj); + } + + /** + * 判断对象不为null + * @param obj + * @return + */ + public static boolean objIsNotNull(Object obj){ + return !Objects.isNull(obj); + } + + /** + * 字符串为空 + * @return + */ + public static boolean isBlank(String str){ + int strLen; + if (str == null || (strLen = str.length()) == 0){ + return Boolean.TRUE; + } + for (int i = 0; i< strLen; i++){ + if ((Character.isWhitespace(str.charAt(i)) == false)){ + return false; + } + } + return true; + } + + /** + * 获取md5摘要 + * @param content + * @return + */ + public static String getMd5(String content){ + if (isBlank(content)){ + return content; + } + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.reset(); + md5.update(content.getBytes(StandardCharsets.UTF_8)); + return Hex.encodeHexString(md5.digest()); + } catch (NoSuchAlgorithmException e) { + log.warn("getMd5 fail = {}",e.getMessage()); + } + return content; + } + + /** + * 获取文件的MD5值 + * @param bytes + * @return + */ + public static String getMd5(byte [] bytes) { + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.reset(); + md5.update(bytes); + return Hex.encodeHexString(md5.digest()); + } catch (NoSuchAlgorithmException e) { + log.warn("getMd5 fail = {}",e.getMessage()); + } + return ""; + } + + /** + * 容量换算 + * @return + */ + public static int capacityConversion(int size, String storageUnit) { + StorageUnitEnum storageUnitEnum = StorageUnitEnum.valueOf(storageUnit); + if (objIsNull(storageUnitEnum)) { + return 0; + } + return storageUnitEnum.getSize() * size; + } + + /** + * 生成UUID + * @return + */ + public static String getUUID(){ + return UUID.randomUUID().toString().replaceAll("-",""); + } + + /** + * 生成file key + * @return + */ + public static String generateFileKey(String directory, String fileUuid, String fileFormat){ + StringBuilder tgtFileKey = new StringBuilder(directory); + tgtFileKey.append(FileClassEnum.SEPARATOR_CHAR.type); + tgtFileKey.append(fileUuid); + tgtFileKey.append(FileClassEnum.DOT.type); + tgtFileKey.append(fileFormat); + return tgtFileKey.toString(); + } +} diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java index d9db5c3..1319b72 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java @@ -2,6 +2,7 @@ package cn.axzo.oss.dal.repository; import cn.axzo.oss.dal.entity.AppChannelBucket; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; /** *

@@ -13,4 +14,11 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface AppChannelBucketDao extends IService { + /** + * 通过appcode获取文件渠道桶信息 + * + * @param appCode appcode + * @return + */ + List getByAppCode(String appCode); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java index 642606b..7966b48 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java @@ -13,4 +13,10 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface FileAppDao extends IService { + /** + * 通过appCode获取应用信息 + * @param appCode + * @return + */ + FileApp getByAppCode(String appCode); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java index 80078ec..7b2c8ea 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java @@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface FileBusinessSceneDao extends IService { + /** + * 指定appcode文件业务场景 + * + * @param bucketNo 应用编码 + * @param bizScene + * @return + */ + FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java index 28cfecd..379a7fb 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java @@ -2,6 +2,7 @@ package cn.axzo.oss.dal.repository; import cn.axzo.oss.dal.entity.FileChannel; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; /** *

@@ -13,4 +14,10 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface FileChannelDao extends IService { + /** + * 通过channelCode获取最高优化级可用文件渠道 + * @param channelCodes + * @return + */ + List getByChannelCode(List channelCodes); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java index 8da293e..64f0f7b 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java @@ -13,4 +13,11 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface FileDao extends IService { + /** + * 根据url md5获取文件信息 + * @param appCode + * @param urlMd5 + * @return + */ + File getByAppCodeAndUrlMd5(String appCode, String urlMd5); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java index 16e9364..7fb886b 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java @@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface FileUploadConfigDao extends IService { + /** + * 通过渠道码和桶名称获取获取指定上传配置 + * + * @param bucketNo + * @param directory + * @return + */ + FileUploadConfig getByUploadConfig(String bucketNo, String directory); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java index d9f2272..1f17e61 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java @@ -1,9 +1,11 @@ package cn.axzo.oss.dal.repository.impl; +import cn.axzo.oss.common.enums.IsDeleteEnum; import cn.axzo.oss.dal.entity.AppChannelBucket; import cn.axzo.oss.dal.mapper.AppChannelBucketMapper; import cn.axzo.oss.dal.repository.AppChannelBucketDao; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.util.List; import org.springframework.stereotype.Repository; /** @@ -15,6 +17,18 @@ import org.springframework.stereotype.Repository; * @since 2021-07-23 */ @Repository("appChannelBucketDao") -public class AppChannelBucketDaoImpl extends ServiceImpl implements AppChannelBucketDao { +public class AppChannelBucketDaoImpl extends + ServiceImpl implements AppChannelBucketDao { + /** + * 通过appcode获取文件渠道桶信息 + * + * @param appCode appcode + * @return + */ + @Override + public List getByAppCode(String appCode) { + return lambdaQuery().eq(AppChannelBucket::getAppCode, appCode) + .eq(AppChannelBucket::getIsDelete, IsDeleteEnum.NO.getCode()).list(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java index fce99b7..cf3850c 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java @@ -1,5 +1,6 @@ package cn.axzo.oss.dal.repository.impl; +import cn.axzo.oss.common.enums.IsDeleteEnum; import cn.axzo.oss.dal.entity.FileApp; import cn.axzo.oss.dal.mapper.FileAppMapper; import cn.axzo.oss.dal.repository.FileAppDao; @@ -17,4 +18,17 @@ import org.springframework.stereotype.Repository; @Repository("fileAppDao") public class FileAppDaoImpl extends ServiceImpl implements FileAppDao { + + /** + * 通过appCode获取应用信息 + * + * @param appCode + * @return + */ + @Override + public FileApp getByAppCode(String appCode) { + return lambdaQuery().eq(FileApp::getAppCode, appCode) + .eq(FileApp::getStatus, 1) + .eq(FileApp::getIsDelete, IsDeleteEnum.NO.getCode()).one(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java index 9cd9f12..51806ed 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java @@ -1,5 +1,6 @@ package cn.axzo.oss.dal.repository.impl; +import cn.axzo.oss.common.enums.IsDeleteEnum; import cn.axzo.oss.dal.entity.FileBusinessScene; import cn.axzo.oss.dal.mapper.FileBusinessSceneMapper; import cn.axzo.oss.dal.repository.FileBusinessSceneDao; @@ -15,6 +16,19 @@ import org.springframework.stereotype.Repository; * @since 2021-07-23 */ @Repository("fileBusinessSceneDao") -public class FileBusinessSceneDaoImpl extends ServiceImpl implements FileBusinessSceneDao { +public class FileBusinessSceneDaoImpl extends + ServiceImpl implements FileBusinessSceneDao { + /** + * 指定appcode文件业务场景 + * + * @param bucketNo + * @return + */ + @Override + public FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScen) { + return lambdaQuery().eq(FileBusinessScene::getAppChannelBucketNo, bucketNo) + .eq(FileBusinessScene::getBusinessScene,bizScen) + .eq(FileBusinessScene::getIsDelete, IsDeleteEnum.NO.getCode()).one(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java index 558d91d..6458b3a 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java @@ -4,6 +4,7 @@ import cn.axzo.oss.dal.entity.FileChannel; import cn.axzo.oss.dal.mapper.FileChannelMapper; import cn.axzo.oss.dal.repository.FileChannelDao; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.util.List; import org.springframework.stereotype.Repository; /** @@ -17,4 +18,16 @@ import org.springframework.stereotype.Repository; @Repository("fileChannelDao") public class FileChannelDaoImpl extends ServiceImpl implements FileChannelDao { + /** + * 通过channelCode获取多个可用文件渠道 + * + * @param channelCodes + * @return + */ + @Override + public List getByChannelCode(List channelCodes) { + return lambdaQuery().in(FileChannel::getChannelCode,channelCodes) + .eq(FileChannel::getStatus,1) + .orderByAsc(FileChannel::getPriority).list(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java index 83924b6..c6da68c 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java @@ -1,5 +1,7 @@ package cn.axzo.oss.dal.repository.impl; +import cn.axzo.oss.common.constans.CommonConstants.FileStatus; +import cn.axzo.oss.common.constans.CommonConstants.TableDelete; import cn.axzo.oss.dal.entity.File; import cn.axzo.oss.dal.mapper.FileMapper; import cn.axzo.oss.dal.repository.FileDao; @@ -17,4 +19,10 @@ import org.springframework.stereotype.Repository; @Repository("fileDao") public class FileDaoImpl extends ServiceImpl implements FileDao { + @Override + public File getByAppCodeAndUrlMd5(String appCode, String urlMd5) { + return lambdaQuery().eq(File::getAppCode, appCode).eq(File::getUrlMd5, urlMd5) + .eq(File::getStatus, FileStatus.SUCCESS).eq(File::getIsDelete, TableDelete.UN_DELETED) + .last("limit 1").one(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java index 24f506a..9557cff 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java @@ -1,5 +1,6 @@ package cn.axzo.oss.dal.repository.impl; +import cn.axzo.oss.common.enums.IsDeleteEnum; import cn.axzo.oss.dal.entity.FileUploadConfig; import cn.axzo.oss.dal.mapper.FileUploadConfigMapper; import cn.axzo.oss.dal.repository.FileUploadConfigDao; @@ -15,6 +16,20 @@ import org.springframework.stereotype.Repository; * @since 2021-07-23 */ @Repository("fileUploadConfigDao") -public class FileUploadConfigDaoImpl extends ServiceImpl implements FileUploadConfigDao { +public class FileUploadConfigDaoImpl extends + ServiceImpl implements FileUploadConfigDao { + /** + * 通过渠道码和桶名称获取获取指定上传配置 + * + * @param bucketNo + * @param directory + * @return + */ + @Override + public FileUploadConfig getByUploadConfig(String bucketNo, String directory) { + return lambdaQuery().eq(FileUploadConfig::getAppChannelBucketNo, bucketNo) + .eq(FileUploadConfig::getDirectory, directory) + .eq(FileUploadConfig::getIsDelete, IsDeleteEnum.NO.getCode()).one(); + } } diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java index 133b504..ec590f9 100644 --- a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.RequestMethod; */ @FeignClient( name = "oss", - url = "http://oss" + url = "http://oss:9123" ) @RequestMapping(value = "/api/v1/server") public interface ServerFileServiceApi { diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java index 7bc9314..d789bcf 100644 --- a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java @@ -14,7 +14,13 @@ import javax.validation.constraints.NotBlank; @Data public class ServerFileDeleteRequest { + @NotBlank(message = "appCode must not be null") + private String appCode; + @NotBlank(message = "url must not be null") private String url; + @NotBlank(message = "operator must not be null") + private String operator; + } diff --git a/oss-integration/pom.xml b/oss-integration/pom.xml index 969c205..28db6e2 100644 --- a/oss-integration/pom.xml +++ b/oss-integration/pom.xml @@ -19,7 +19,11 @@ org.springframework.cloud spring-cloud-starter-openfeign - + + com.aliyun.oss + aliyun-sdk-oss + + diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java new file mode 100644 index 0000000..8808762 --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java @@ -0,0 +1,13 @@ +package cn.axzo.oss.integration.s3; + +import cn.axzo.oss.integration.s3.base.BaseS3Service; + +/** + * @program: oss + * @description: 阿里云oss服务 + * @author: mr.jie + * @date: 2021-07-29 15:44 + **/ +public interface AliOssService extends BaseS3Service { + +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java new file mode 100644 index 0000000..06639bf --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java @@ -0,0 +1,55 @@ +package cn.axzo.oss.integration.s3.base; + +import java.io.FilterInputStream; +import java.io.InputStream; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 23:46 + * @Version 0.0.1 + **/ +public interface BaseS3Service { + + int RECORD_LIMIT = 100; + // ttl 15m; 60 * 15 = 900s + int DEFAULT_TTL_S = 900; + + /** + * upload file + */ + String uploadByStream(String bucketName, String tgtFileKey, InputStream srcStream); + + /** + * upload multi file + */ + boolean uploadMultiFile(MultipartFile[] multipartFiles); + + /** + * delete file + */ + boolean delFile(String bucket, String tgtFileKey); + + + /** + * download file + */ + ResponseEntity download(String tgtFileKey); + + /** + * get file address + * + * @param ttl second + */ + String getFileAddress(String tgtFileKey, int ttl); + + /** + * get S3Object stream + */ + FilterInputStream getS3ObjectStream(String tgtFileKey); + + + +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java new file mode 100644 index 0000000..97b9020 --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java @@ -0,0 +1,17 @@ +package cn.axzo.oss.integration.s3.base; + +/** + * @program: oss + * @description: 客户端接口 + * @author: mr.jie + * @date: 2021-07-29 18:07 + **/ +public interface OssClientBase { + + Object getClient(); + + void initClient(); + + String getEndpoint(); + +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java new file mode 100644 index 0000000..ce5911a --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java @@ -0,0 +1,55 @@ +package cn.axzo.oss.integration.s3.client; + + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.S3Exception; +import cn.axzo.oss.common.utils.Utility; +import cn.axzo.oss.integration.s3.base.OssClientBase; +import cn.axzo.oss.integration.s3.config.AliOssConfig; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import javax.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @program: oss + * @description: 阿里云服务客户端 + * @author: mr.jie + * @date: 2021-07-29 15:49 + **/ +@Component +@Slf4j +public class AliOssClient implements OssClientBase { + private volatile static OSS instance = null; + + @Autowired + private AliOssConfig aliOssConfig; + + public OSS getClient(){ + if (Utility.objIsNull(instance)){ + throw new S3Exception(CodeEnum.S3_CLIENT_NULL.getCode(),"oss客户端未初始化"); + } + return instance; + } + + + @PostConstruct + @Override + public void initClient(){ + log.info("initClient endpoint = {}, accessKeyId = {},secretAccessKey = {}", aliOssConfig.getEndpoint(),aliOssConfig.getAccessKeyId(),aliOssConfig.getSecretAccessKey()); + try { + instance = new OSSClientBuilder().build(aliOssConfig.getEndpoint(),aliOssConfig.getAccessKeyId(),aliOssConfig.getSecretAccessKey()); + } catch (Exception e) { + instance = null; + log.error("initClient error = {}", e); + } + } + + @Override + public String getEndpoint(){ + return aliOssConfig.getEndpoint(); + } + +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java new file mode 100644 index 0000000..8851f93 --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java @@ -0,0 +1,35 @@ +package cn.axzo.oss.integration.s3.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @program: oss + * @description: 阿里云配置 + * @author: mr.jie + * @date: 2021-07-29 17:57 + **/ +@Component +public class AliOssConfig { + + @Value("${aliyun.oss.accessKeyId}") + private String ACCESS_KEY_ID; + + @Value("${aliyun.oss.secretAccessKey}") + private String SECRET_ACCESS_KEY; + + @Value("${aliyun.oss.endpoint}") + private String ENDPOINT; + + public String getAccessKeyId(){ + return this.ACCESS_KEY_ID; + } + + public String getSecretAccessKey(){ + return this.SECRET_ACCESS_KEY; + } + + public String getEndpoint(){ + return this.ENDPOINT; + } +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java new file mode 100644 index 0000000..57821c9 --- /dev/null +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java @@ -0,0 +1,103 @@ +package cn.axzo.oss.integration.s3.impl; + +import cn.axzo.oss.integration.s3.AliOssService; +import cn.axzo.oss.integration.s3.client.AliOssClient; +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSException; +import java.io.FilterInputStream; +import java.io.InputStream; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +/** + * @program: oss + * @description: 阿里oss服务 + * @author: mr.jie + * @date: 2021-07-29 15:45 + **/ +@Service +@Slf4j +public class AliOssServiceImpl implements AliOssService { + + @Autowired + private AliOssClient aliOssClient; + + /** + * upload file + */ + @Override + public String uploadByStream(String bucketName, String tgtFileKey, InputStream srcStream) { + OSS client = aliOssClient.getClient(); + try { + client.putObject(bucketName, tgtFileKey, srcStream); + } catch (OSSException e) { + log.error("uploadByStream OSSException", e); + return ""; + } catch (ClientException e) { + log.error("uploadByStream ClientException", e); + return ""; + } + + StringBuilder allBuilder = new StringBuilder(); + allBuilder.append("https://"); + allBuilder.append(bucketName); + allBuilder.append("."); + allBuilder.append(aliOssClient.getEndpoint()); + allBuilder.append(tgtFileKey); + + return allBuilder.toString(); + } + + /** + * upload multi file + */ + @Override + public boolean uploadMultiFile(MultipartFile[] multipartFiles) { + return false; + } + + /** + * delete file + */ + @Override + public boolean delFile(String bucket, String tgtFileKey) { + log.debug("ali oss delFile bucket = {}, tatFileKey = {}", bucket, tgtFileKey); + try { + aliOssClient.getClient().deleteObject(bucket, tgtFileKey); + return Boolean.TRUE; + } catch (Exception e) { + log.error("ali oss delFile error = {}", e); + } + return Boolean.FALSE; + } + + /** + * download file + */ + @Override + public ResponseEntity download(String tgtFileKey) { + return null; + } + + /** + * get file address + * + * @param ttl second + */ + @Override + public String getFileAddress(String tgtFileKey, int ttl) { + return null; + } + + /** + * get S3Object stream + */ + @Override + public FilterInputStream getS3ObjectStream(String tgtFileKey) { + return null; + } +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java new file mode 100644 index 0000000..00d1b7b --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java @@ -0,0 +1,20 @@ +package cn.axzo.oss.manager.api; + +import cn.axzo.oss.dal.entity.AppChannelBucket; +import java.util.List; + +/** + * @author: zhangran + * @date: 20210803 15:30 + * @description: + **/ +public interface AppChannelBucketManager { + + /** + * 通过appcode获取文件渠道桶信息 + * + * @param appCode appcode + * @return + */ + AppChannelBucket getByAppCode(String appCode); +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java new file mode 100644 index 0000000..01a16ff --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java @@ -0,0 +1,21 @@ +package cn.axzo.oss.manager.api; + +import cn.axzo.oss.dal.entity.FileApp; + +/** + * @author: zhangran + * @date: 20210803 15:28 + * @description: + **/ +public interface FileAppManager { + + /** + * 通过appCode获取应用信息 + * + * @param appCode + * @return + */ + FileApp getByAppCode(String appCode); + + +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java new file mode 100644 index 0000000..772b09e --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java @@ -0,0 +1,20 @@ +package cn.axzo.oss.manager.api; + +import cn.axzo.oss.dal.entity.FileBusinessScene; + +/** + * @author: zhangran + * @date: 20210803 15:42 + * @description: + **/ +public interface FileBusinessSceneManager { + + /** + * 指定appcode文件业务场景 + * + * @param bucketNo 应用编码 + * @param bizScene + * @return + */ + FileBusinessScene getByBucketNoAndScene(String bucketNo,String bizScene); +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java new file mode 100644 index 0000000..be1a250 --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java @@ -0,0 +1,29 @@ +package cn.axzo.oss.manager.api; + +import cn.axzo.oss.dal.entity.AppChannelBucket; +import cn.axzo.oss.dal.entity.FileChannel; +import java.util.List; + +/** + * @author: zhangran + * @date: 20210803 15:33 + * @description: + **/ +public interface FileChannelManager { + + /** + * 返回所有渠道 按优先级升序返回 + * + * @param channelCodes + * @return + */ + List listChannelCodeOrderByPriorityAsc(List channelCodes); + + /** + * 返回一个最优的渠道 升序第一个 + * + * @param appChannelBuckets + * @return + */ + FileChannel getOptimalChannel(List appChannelBuckets ); +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java new file mode 100644 index 0000000..b5355ea --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java @@ -0,0 +1,29 @@ +package cn.axzo.oss.manager.api; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:48 + * @Version 0.0.1 + **/ +public interface FileManager { + + /** + * 删除文件 + * @param bucketName 桶名称 + * @param tgtFileKey 目标文件key + * @return + */ + boolean delete(String bucketName, String tgtFileKey); + + /** + * 上传 + * + * @param bulkName + * @param keyPath + * @param fileContent + * @return + */ + String uploadByStream(String bulkName, String keyPath, byte[] fileContent); + +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java new file mode 100644 index 0000000..e3229fc --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java @@ -0,0 +1,20 @@ +package cn.axzo.oss.manager.api; + +import cn.axzo.oss.dal.entity.FileUploadConfig; + +/** + * @author: zhangran + * @date: 20210803 15:43 + * @description: + **/ +public interface FileUploadConfigManager { + + /** + * 通过渠道码和桶名称获取获取指定上传配置 + * + * @param bucketNo + * @param directory + * @return + */ + FileUploadConfig getByUploadConfig(String bucketNo, String directory); +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java new file mode 100644 index 0000000..1bc1ed7 --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java @@ -0,0 +1,26 @@ +package cn.axzo.oss.manager.api.dto.request; + +import lombok.Data; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:50 + * @Version 0.0.1 + **/ +@Data +public class ServerFileDeleteDto { + + /** + * 应用码 + */ + private String appCode; + /** + * 文件地址 + */ + private String url; + /** + * 操作人 + */ + private String operator; +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java new file mode 100644 index 0000000..c290db6 --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java @@ -0,0 +1,19 @@ +package cn.axzo.oss.manager.api.dto.request; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @program: oss + * @description: 文件上传 + * @author: mr.jie + * @date: 2021-07-29 18:31 + **/ +@Data +public class ServerFileUploadDto { + private String appCode; + private String bizScene; + private String fileName; + private byte[] fileContent; +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java new file mode 100644 index 0000000..83b4ee5 --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java @@ -0,0 +1,11 @@ +package cn.axzo.oss.manager.api.dto.response; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:51 + * @Version 0.0.1 + **/ +public class ServerFileDeleteResponse { + +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java new file mode 100644 index 0000000..3f981ae --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java @@ -0,0 +1,28 @@ +package cn.axzo.oss.manager.api.dto.response; + +import lombok.Data; + +/** + * 服务端文件上传响应类 + * + * @author zhaoyong + * @see ServerFileUploadResponse + * @since 2021-07-23 10:37 + */ +@Data +public class ServerFileUploadResponse { + + /** + * 文件 URL + */ + private String url; + /** + * 文件 Key + */ + private String fileKey; + /** + * URL MD5 + */ + private String urlMd5; + +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java new file mode 100644 index 0000000..0e2b155 --- /dev/null +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java @@ -0,0 +1,51 @@ +package cn.axzo.oss.manager.impl; + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.dal.entity.AppChannelBucket; +import cn.axzo.oss.dal.entity.FileChannel; +import cn.axzo.oss.dal.repository.AppChannelBucketDao; +import cn.axzo.oss.manager.api.AppChannelBucketManager; +import cn.axzo.oss.manager.api.FileChannelManager; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author: zhangran + * @date: 20210803 15:44 + * @description: + **/ +@Service +@Slf4j +public class AppChannelBucketManagerImpl implements AppChannelBucketManager { + + @Autowired + private AppChannelBucketDao appChannelBucketDao; + + @Autowired + private FileChannelManager fileChannelManager; + + /** + * 通过appcode获取文件渠道桶信息 + * + * @param appCode appcode + * @return + */ + @Override + public AppChannelBucket getByAppCode(String appCode) { + List appChannelBuckets = appChannelBucketDao.getByAppCode(appCode); + BizException.isEmpty(appChannelBuckets, CodeEnum.APP_CHANNEL_BUCKET_NOT_FOUND); + + // 找到最优渠道 + FileChannel fileChannel = fileChannelManager.getOptimalChannel(appChannelBuckets); + + AppChannelBucket appChannelBucket = appChannelBuckets.stream().filter(bucket -> + bucket.getChannelCode().equals(fileChannel.getChannelCode())) + .findFirst().orElse(null); + BizException.isEmpty(appChannelBucket, CodeEnum.APP_CHANNEL_NOT_FOUND); + + return appChannelBucket; + } +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java new file mode 100644 index 0000000..7e542ce --- /dev/null +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java @@ -0,0 +1,38 @@ +package cn.axzo.oss.manager.impl; + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.dal.entity.FileBusinessScene; +import cn.axzo.oss.dal.repository.FileBusinessSceneDao; +import cn.axzo.oss.manager.api.FileBusinessSceneManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author: zhangran + * @date: 20210803 16:36 + * @description: + **/ +@Service +@Slf4j +public class FileBusinessSceneManagerImpl implements FileBusinessSceneManager { + + @Autowired + private FileBusinessSceneDao fileBusinessSceneDao; + + /** + * 指定appcode文件业务场景 + * + * @param bucketNo 应用编码 + * @param bizScene + * @return + */ + @Override + public FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene) { + FileBusinessScene fileBusinessScene = fileBusinessSceneDao + .getByBucketNoAndScene(bucketNo, bizScene); + BizException.isEmpty(fileBusinessScene, CodeEnum.APP_CHANNEL_NOT_FOUND); + return fileBusinessScene; + } +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java new file mode 100644 index 0000000..529d680 --- /dev/null +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java @@ -0,0 +1,56 @@ +package cn.axzo.oss.manager.impl; + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.dal.entity.AppChannelBucket; +import cn.axzo.oss.dal.entity.FileChannel; +import cn.axzo.oss.dal.repository.FileChannelDao; +import cn.axzo.oss.manager.api.FileChannelManager; +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author: zhangran + * @date: 20210803 16:28 + * @description: + **/ +@Service +@Slf4j +public class FileChannelManagerImpl implements FileChannelManager { + + @Autowired + private FileChannelDao fileChannelDao; + + /** + * 返回所有渠道 按优先级升序返回 + * + * @param channelCodes + * @return + */ + @Override + public List listChannelCodeOrderByPriorityAsc(List channelCodes) { + List fileChannels = fileChannelDao.getByChannelCode(channelCodes); + BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND); + return fileChannels; + } + + /** + * 返回一个最优的渠道 升序第一个 + * + * @param appChannelBuckets + * @return + */ + @Override + public FileChannel getOptimalChannel(List appChannelBuckets ) { + ArrayList channels = Lists.newArrayList(); + appChannelBuckets.forEach(appChannelBucket -> channels.add(appChannelBucket.getChannelCode())); + + List fileChannels = fileChannelDao.getByChannelCode(channels); + BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND); + return fileChannels.get(0); + } +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java new file mode 100644 index 0000000..45bf80b --- /dev/null +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java @@ -0,0 +1,46 @@ +package cn.axzo.oss.manager.impl; + +import cn.axzo.oss.integration.s3.AliOssService; +import cn.axzo.oss.manager.api.FileManager; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:48 + * @Version 0.0.1 + **/ +@Service +@Slf4j +public class FileManagerImpl implements FileManager { + + @Autowired + private AliOssService aliOssService; + + /** + * 删除文件 + * @param bucketName 桶名称 + * @param tgtFileKey 目标文件key + * @return + */ + @Override + public boolean delete(String bucketName, String tgtFileKey) { + return aliOssService.delFile(bucketName, tgtFileKey); + } + + /** + * @param bulkName 默认的取值为 + * @param keyPath key的前置路径 + */ + public String uploadByStream(String bulkName, String keyPath, byte[] fileContent) { + + InputStream inputStream = new ByteArrayInputStream(fileContent); + + return aliOssService.uploadByStream(bulkName, keyPath, inputStream); + } + +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java new file mode 100644 index 0000000..9b8f94b --- /dev/null +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java @@ -0,0 +1,37 @@ +package cn.axzo.oss.manager.impl; + +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.dal.entity.FileUploadConfig; +import cn.axzo.oss.dal.repository.FileUploadConfigDao; +import cn.axzo.oss.manager.api.FileUploadConfigManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author: zhangran + * @date: 20210803 16:39 + * @description: + **/ +@Service +@Slf4j +public class FileUploadConfigManagerImpl implements FileUploadConfigManager { + + @Autowired + private FileUploadConfigDao fileUploadConfigDao; + + /** + * 通过渠道码和桶名称获取获取指定上传配置 + * + * @param bucketNo + * @param directory + * @return + */ + @Override + public FileUploadConfig getByUploadConfig(String bucketNo, String directory) { + FileUploadConfig uploadConfig = fileUploadConfigDao.getByUploadConfig(bucketNo, directory); + BizException.isEmpty(uploadConfig, CodeEnum.NO_UPLOAD_CONFIG); + return uploadConfig; + } +} diff --git a/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java new file mode 100644 index 0000000..fafed85 --- /dev/null +++ b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java @@ -0,0 +1,28 @@ +package cn.axzo.oss.service.api; + +import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto; +import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto; +import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:48 + * @Version 0.0.1 + **/ +public interface FileService { + + /** + * 删除文件 + * + * @param dto + */ + void delete(ServerFileDeleteDto dto); + + /** + * 上传 + * + * @param request + */ + ServerFileUploadResponse upload(ServerFileUploadDto request); +} diff --git a/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..f290b25 --- /dev/null +++ b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java @@ -0,0 +1,204 @@ +package cn.axzo.oss.service.impl; + +import cn.axzo.oss.common.constans.CommonConstants; +import cn.axzo.oss.common.constans.CommonConstants.FileStatus; +import cn.axzo.oss.common.constans.CommonConstants.TableDelete; +import cn.axzo.oss.common.enums.CodeEnum; +import cn.axzo.oss.common.enums.FileClassEnum; +import cn.axzo.oss.common.enums.FileStatusEnum; +import cn.axzo.oss.common.exception.BizException; +import cn.axzo.oss.common.utils.JsonUtil; +import cn.axzo.oss.common.utils.Utility; +import cn.axzo.oss.dal.entity.AppChannelBucket; +import cn.axzo.oss.dal.entity.File; +import cn.axzo.oss.dal.entity.FileApp; +import cn.axzo.oss.dal.entity.FileBusinessScene; +import cn.axzo.oss.dal.entity.FileUploadConfig; +import cn.axzo.oss.dal.repository.FileAppDao; +import cn.axzo.oss.dal.repository.FileDao; +import cn.axzo.oss.manager.api.AppChannelBucketManager; +import cn.axzo.oss.manager.api.FileBusinessSceneManager; +import cn.axzo.oss.manager.api.FileManager; +import cn.axzo.oss.manager.api.FileUploadConfigManager; +import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto; +import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto; +import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse; +import cn.axzo.oss.service.api.FileService; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @Author admin + * @Description + * @Date 2021/7/28 22:48 + * @Version 0.0.1 + **/ +@Service +@Slf4j +public class FileServiceImpl implements FileService { + + @Autowired + private FileManager fileManager; + + @Autowired + private FileDao fileDao; + + @Autowired + private FileAppDao fileAppDao; + @Autowired + private AppChannelBucketManager appChannelBucketManager; + @Autowired + private FileBusinessSceneManager fileBusinessSceneManager; + @Autowired + private FileUploadConfigManager fileUploadConfigManager; + + + /** + * 删除文件 + * + * @param dto + */ + @Override + public void delete(ServerFileDeleteDto dto) { + log.info("delete dto = {}", JsonUtil.obj2Str(dto)); + // 检查app code + checkAppCode(dto.getAppCode()); + + String urlMd5 = Utility.getMd5(dto.getUrl()); + log.info("delete urlMd5 = {}", urlMd5); + + File file = fileDao.getByAppCodeAndUrlMd5(dto.getAppCode(), urlMd5); + if (Utility.objIsNull(file)) { + log.warn("delete file is null,url = {}, urlMd5 = {}", dto.getUrl(), urlMd5); + return; + } + String tgtFileKey = Utility + .generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat()); + log.debug("delete tgtFileKey = {}", tgtFileKey); + boolean deleteFlag = fileManager.delete(file.getBucketName(), tgtFileKey); + log.info("delete deleteFlag = {}", deleteFlag); + if (deleteFlag) { + File updateFile = new File(); + updateFile.setIsDelete(TableDelete.DELETED); + updateFile.setStatus(FileStatus.DELETED); + updateFile.setUpdateBy(dto.getOperator()); + updateFile.setId(file.getId()); + fileDao.updateById(updateFile); + } + } + + + /** + * 检查appCode是否有效 + * + * @param appCode + */ + private void checkAppCode(final String appCode) { + log.info("checkAppCode appCode = {}", appCode); + FileApp fileApp = fileAppDao.getByAppCode(appCode); + BizException.error(Utility.objIsNotNull(fileApp), CodeEnum.APP_CODE_NOT_FOUND); + } + + /** + * 上传 + * + * @param dto + */ + @Override + public ServerFileUploadResponse upload(ServerFileUploadDto dto) { + log.info("update fileName:{},appCode:{},bizScene:{}", + dto.getFileName(), dto.getAppCode(), dto.getBizScene()); + // 检查appCode + checkAppCode(dto.getAppCode()); + + // 通过appcode获取文件渠道桶信息 + AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(dto.getAppCode()); + + // 通过渠道桶编码获取到具体文件业务场景 + FileBusinessScene scene = fileBusinessSceneManager + .getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), dto.getBizScene()); + + // 通过渠道码和桶名称获取获取指定上传配置 + FileUploadConfig fileUploadConfig = fileUploadConfigManager + .getByUploadConfig(scene.getAppChannelBucketNo(), scene.getDirectory()); + + // 上传文件并生成file对象 + File ossFile = generateFile(fileUploadConfig, dto); + + return setResponse(ossFile); + } + + /** + * 判断文件是否符合要求 + */ + private String isFileConform(FileUploadConfig fileUploadConfig, int fileLength, String fileName) { + // 文件大小超出上限 + int size = Utility + .capacityConversion(fileUploadConfig.getStorageSize(), fileUploadConfig.getStorageUnit()); + BizException.error(size > fileLength, CodeEnum.FILE_SIZE_EXCEEDS_LIMIT); + // 文件格式判断 + String[] formats = fileUploadConfig.getFileFormat().split(FileClassEnum.COMMA.type); + + int lastIndexOf = fileName.lastIndexOf(FileClassEnum.DOT.type); + BizException + .error(lastIndexOf != CommonConstants.NOT_FOUND_INDEX_OF, CodeEnum.NOT_FILE_FORMAT); + + // 是否包含指定格式 + String fileFormat = fileName.substring(lastIndexOf + CommonConstants.ONE).toLowerCase(); + boolean contains = Arrays.asList(formats).contains(fileFormat); + BizException.error(contains, CodeEnum.FILE_FORMAT_NOT_SUPPORTED); + + return fileFormat; + } + + private File generateFile(FileUploadConfig fileUploadConfig, ServerFileUploadDto dto) { + // 判断容量 + String fileConform = isFileConform(fileUploadConfig, dto.getFileContent().length, + dto.getFileName()); + + String uuid = Utility.getUUID(); + + // 生成上传文件的唯一key + String tgtFileKey = Utility.generateFileKey(fileUploadConfig.getDirectory(), uuid, fileConform); + + File ossFile = new File(); + ossFile.setAppChannelBucketNo(fileUploadConfig.getAppChannelBucketNo()); + ossFile.setAppCode(fileUploadConfig.getAppCode()); + ossFile.setChannelCode(fileUploadConfig.getChannelCode()); + ossFile.setBucketName(fileUploadConfig.getBucketName()); + ossFile.setDirectory(fileUploadConfig.getDirectory()); + ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_FAIL.getCode()); + ossFile.setStorageUnit(fileUploadConfig.getStorageUnit()); + ossFile.setStorageSize(fileUploadConfig.getStorageSize()); + ossFile.setFileFormat(fileConform); + // 上传文件 + String fileUrl = fileManager.uploadByStream( + fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileContent()); + + // 保存失败 + if (Utility.isBlank(fileUrl)) { + fileDao.save(ossFile); + throw new BizException(CodeEnum.FILE_UPLOAD_FAILED); + } + + ossFile.setFileUuid(uuid); + ossFile.setFileUrl(fileUrl); + ossFile.setUrlMd5(Utility.getMd5(fileUrl)); + ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_SUCCESS.getCode()); + ossFile.setFileName(dto.getFileName()); + ossFile.setFileMd5(Utility.getMd5(dto.getFileContent())); + fileDao.save(ossFile); + return ossFile; + } + + private ServerFileUploadResponse setResponse(File ossFile){ + ServerFileUploadResponse response = new ServerFileUploadResponse(); + response.setUrl(ossFile.getFileUrl()); + response.setUrlMd5(ossFile.getUrlMd5()); + response.setFileKey(ossFile.getFileUuid()); + return response; + } + +} diff --git a/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java b/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java new file mode 100644 index 0000000..1b52bdb --- /dev/null +++ b/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java @@ -0,0 +1,61 @@ +package cn.axzo.oss.test; + +import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto; +import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto; +import cn.axzo.oss.service.api.FileService; +import cn.axzo.oss.test.base.SpringTestBase; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @program: oss + * @description: 文件服务测试 + * @author: mr.jie + * @date: 2021-07-29 18:42 + **/ +public class FileServiceTest extends SpringTestBase { + + @Autowired + private FileService fileService; + + @Test + public void deleteTest() { + ServerFileDeleteDto dto = new ServerFileDeleteDto(); + dto.setUrl("https://axzo-public.oss-cn-chengdu.aliyuncs.com/109/108046507ad94bf084aa86c07d743799.jpg"); + dto.setOperator("zhangsan"); + fileService.delete(dto); + } + + + @Test + public void upload() { + ServerFileUploadDto dto = new ServerFileUploadDto(); + dto.setAppCode("test"); + dto.setBizScene("1"); + dto.setFileName("一个新的文件.xlsx"); + + File file = new File("/Users/admin/Downloads/表扬人员名称.xlsx"); + + FileInputStream fileInputStream = null; + + byte[] bytes = new byte[(int) file.length()]; + try { + fileInputStream = new FileInputStream(file); + fileInputStream.read(bytes); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } +// System.out.println(Arrays.toString(bytes)); + dto.setFileContent(bytes); +// +// fileService.upload(dto); + } + + +} diff --git a/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java b/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java new file mode 100644 index 0000000..60787f6 --- /dev/null +++ b/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java @@ -0,0 +1,18 @@ +package cn.axzo.oss.test.base; + +import cn.axzo.oss.client.Bootstrap; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @program: oss + * @description: 测试基础 + * @author: mr.jie + * @date: 2021-07-29 18:43 + **/ +@SpringBootTest(classes = Bootstrap.class) +@RunWith(SpringJUnit4ClassRunner.class) +public class SpringTestBase { + +} diff --git a/pom.xml b/pom.xml index 39ffefb..6b5551c 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,8 @@ 2.0 2.2.1.RELEASE Hoxton.SR6 + 1.10 + 3.10.2 @@ -157,6 +159,16 @@ xxl-job-core ${xxl.job.version} + + commons-codec + commons-codec + ${commons-codec.version} + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun-oss.version} +