Merge branch 'feature/rm_up_file' into 'master'
Feature/rm up file See merge request shanghai/oss!1
This commit is contained in:
commit
b96234b0ad
@ -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='文件上传记录';
|
||||
14
doc/sql/dml/oss_data_init.sql
Normal file
14
doc/sql/dml/oss_data_init.sql
Normal file
@ -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');
|
||||
@ -106,6 +106,14 @@
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<ServerFileUploadResponse> upload(@Valid @RequestBody ServerFileUploadRequest request) {
|
||||
return null;
|
||||
}
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Override
|
||||
public CommonResponse<ServerFileUploadResponse> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>cn.axzo.oss</groupId>
|
||||
<artifactId>oss</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<artifactId>oss-common</artifactId>
|
||||
|
||||
@ -70,6 +70,10 @@
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Integer> {
|
||||
|
||||
/**
|
||||
* 系统返回码枚举类
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -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<Integer> {
|
||||
/**
|
||||
* 处理中
|
||||
*/
|
||||
STATUS_PROCESSING(0, "处理中"),
|
||||
/**
|
||||
* 上传成功
|
||||
*/
|
||||
STATUS_UPLOAD_SUCCESS(1, "上传成功"),
|
||||
/**
|
||||
* 上传失败
|
||||
*/
|
||||
STATUS_UPLOAD_FAIL(2, "上传失败"),
|
||||
/**
|
||||
* 已删除
|
||||
*/
|
||||
STATUS_DELETE(3, "已删除"),
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String message;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -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> T copyBean(Object source, Class<T> 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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
128
oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java
Normal file
128
oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -13,4 +14,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface AppChannelBucketDao extends IService<AppChannelBucket> {
|
||||
|
||||
/**
|
||||
* 通过appcode获取文件渠道桶信息
|
||||
*
|
||||
* @param appCode appcode
|
||||
* @return
|
||||
*/
|
||||
List<AppChannelBucket> getByAppCode(String appCode);
|
||||
}
|
||||
|
||||
@ -13,4 +13,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface FileAppDao extends IService<FileApp> {
|
||||
|
||||
/**
|
||||
* 通过appCode获取应用信息
|
||||
* @param appCode
|
||||
* @return
|
||||
*/
|
||||
FileApp getByAppCode(String appCode);
|
||||
}
|
||||
|
||||
@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface FileBusinessSceneDao extends IService<FileBusinessScene> {
|
||||
|
||||
/**
|
||||
* 指定appcode文件业务场景
|
||||
*
|
||||
* @param bucketNo 应用编码
|
||||
* @param bizScene
|
||||
* @return
|
||||
*/
|
||||
FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -13,4 +14,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface FileChannelDao extends IService<FileChannel> {
|
||||
|
||||
/**
|
||||
* 通过channelCode获取最高优化级可用文件渠道
|
||||
* @param channelCodes
|
||||
* @return
|
||||
*/
|
||||
List<FileChannel> getByChannelCode(List<String> channelCodes);
|
||||
}
|
||||
|
||||
@ -13,4 +13,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface FileDao extends IService<File> {
|
||||
|
||||
/**
|
||||
* 根据url md5获取文件信息
|
||||
* @param appCode
|
||||
* @param urlMd5
|
||||
* @return
|
||||
*/
|
||||
File getByAppCodeAndUrlMd5(String appCode, String urlMd5);
|
||||
}
|
||||
|
||||
@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface FileUploadConfigDao extends IService<FileUploadConfig> {
|
||||
|
||||
/**
|
||||
* 通过渠道码和桶名称获取获取指定上传配置
|
||||
*
|
||||
* @param bucketNo
|
||||
* @param directory
|
||||
* @return
|
||||
*/
|
||||
FileUploadConfig getByUploadConfig(String bucketNo, String directory);
|
||||
}
|
||||
|
||||
@ -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<AppChannelBucketMapper, AppChannelBucket> implements AppChannelBucketDao {
|
||||
public class AppChannelBucketDaoImpl extends
|
||||
ServiceImpl<AppChannelBucketMapper, AppChannelBucket> implements AppChannelBucketDao {
|
||||
|
||||
/**
|
||||
* 通过appcode获取文件渠道桶信息
|
||||
*
|
||||
* @param appCode appcode
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<AppChannelBucket> getByAppCode(String appCode) {
|
||||
return lambdaQuery().eq(AppChannelBucket::getAppCode, appCode)
|
||||
.eq(AppChannelBucket::getIsDelete, IsDeleteEnum.NO.getCode()).list();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<FileAppMapper, FileApp> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<FileBusinessSceneMapper, FileBusinessScene> implements FileBusinessSceneDao {
|
||||
public class FileBusinessSceneDaoImpl extends
|
||||
ServiceImpl<FileBusinessSceneMapper, FileBusinessScene> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<FileChannelMapper, FileChannel> implements FileChannelDao {
|
||||
|
||||
/**
|
||||
* 通过channelCode获取多个可用文件渠道
|
||||
*
|
||||
* @param channelCodes
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<FileChannel> getByChannelCode(List<String> channelCodes) {
|
||||
return lambdaQuery().in(FileChannel::getChannelCode,channelCodes)
|
||||
.eq(FileChannel::getStatus,1)
|
||||
.orderByAsc(FileChannel::getPriority).list();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<FileMapper, File> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<FileUploadConfigMapper, FileUploadConfig> implements FileUploadConfigDao {
|
||||
public class FileUploadConfigDaoImpl extends
|
||||
ServiceImpl<FileUploadConfigMapper, FileUploadConfig> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
@ -19,7 +19,11 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
@ -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<byte[]> download(String tgtFileKey);
|
||||
|
||||
/**
|
||||
* get file address
|
||||
*
|
||||
* @param ttl second
|
||||
*/
|
||||
String getFileAddress(String tgtFileKey, int ttl);
|
||||
|
||||
/**
|
||||
* get S3Object stream
|
||||
*/
|
||||
FilterInputStream getS3ObjectStream(String tgtFileKey);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -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();
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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<byte[]> 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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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<FileChannel> listChannelCodeOrderByPriorityAsc(List<String> channelCodes);
|
||||
|
||||
/**
|
||||
* 返回一个最优的渠道 升序第一个
|
||||
*
|
||||
* @param appChannelBuckets
|
||||
* @return
|
||||
*/
|
||||
FileChannel getOptimalChannel(List<AppChannelBucket> appChannelBuckets );
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -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<AppChannelBucket> 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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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<FileChannel> listChannelCodeOrderByPriorityAsc(List<String> channelCodes) {
|
||||
List<FileChannel> fileChannels = fileChannelDao.getByChannelCode(channelCodes);
|
||||
BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND);
|
||||
return fileChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个最优的渠道 升序第一个
|
||||
*
|
||||
* @param appChannelBuckets
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public FileChannel getOptimalChannel(List<AppChannelBucket> appChannelBuckets ) {
|
||||
ArrayList<String> channels = Lists.newArrayList();
|
||||
appChannelBuckets.forEach(appChannelBucket -> channels.add(appChannelBucket.getChannelCode()));
|
||||
|
||||
List<FileChannel> fileChannels = fileChannelDao.getByChannelCode(channels);
|
||||
BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND);
|
||||
return fileChannels.get(0);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
61
oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java
Normal file
61
oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
12
pom.xml
12
pom.xml
@ -37,6 +37,8 @@
|
||||
<velocity-engine-core.version>2.0</velocity-engine-core.version>
|
||||
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
|
||||
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
|
||||
<commons-codec.version>1.10</commons-codec.version>
|
||||
<aliyun-oss.version>3.10.2</aliyun-oss.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@ -157,6 +159,16 @@
|
||||
<artifactId>xxl-job-core</artifactId>
|
||||
<version>${xxl.job.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${aliyun-oss.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user