fix:完善删除文件以及oss客户端服务

This commit is contained in:
“袁杰” 2021-07-29 19:55:37 +08:00
parent a6e849581d
commit 58882e8811
22 changed files with 610 additions and 23 deletions

View File

@ -8,6 +8,7 @@ import cn.axzo.oss.http.model.ServerFileUploadResponse;
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
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;
@ -23,17 +24,19 @@ import javax.validation.Valid;
@RestController
public class ServerFileController implements ServerFileServiceApi {
private final FileService fileService;
public ServerFileController(FileService fileService) {
this.fileService = fileService;
}
@Autowired
private FileService fileService;
@Override
public CommonResponse<ServerFileUploadResponse> upload(@Valid @RequestBody ServerFileUploadRequest request) {
return null;
}
/**
* 根据文件url删除文件
* @param request
* @return
*/
@Override
public CommonResponse delete(@Valid @RequestBody ServerFileDeleteRequest request) {
ServerFileDeleteDto dto = BeanConvertUtil.copyBean(request, ServerFileDeleteDto.class);

View File

@ -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());
}
}

View File

@ -16,4 +16,30 @@ public abstract class CommonConstants {
Integer UN_DELETE = 0;
Integer DELETE = 1;
}
/**
* 文件状态
*/
public interface FileStatus {
/**
* 处理中
*/
Integer PROCESSING = 0;
/**
* 上传成功
*/
Integer SUCCESS = 1;
/**
* 上传失败
*/
Integer FAIL = 2;
/**
* 已删除
*/
Integer DELETED = 3;
}
}

View File

@ -0,0 +1,41 @@
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")
;
private final Integer code;
private final String message;
}

View File

@ -0,0 +1,90 @@
package cn.axzo.oss.common.exception;
import cn.axzo.oss.common.enums.CodeEnum;
import lombok.Getter;
import lombok.Setter;
/**
* 业务异常
*
* @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);
}
}

View File

@ -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 + '\'' +
'}';
}
}

View File

@ -1,5 +1,8 @@
package cn.axzo.oss.common.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

View File

@ -1,6 +1,6 @@
package cn.axzo.oss.dal.repository.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.dal.entity.File;
import cn.axzo.oss.dal.mapper.FileMapper;
@ -21,7 +21,7 @@ public class FileDaoImpl extends ServiceImpl<FileMapper, File> implements FileDa
@Override
public File getFileByUrlMd5(String urlMd5) {
return lambdaQuery().eq(File::getUrlMd5, urlMd5).eq(File::getIsDelete, TableDelete.UN_DELETE)
return lambdaQuery().eq(File::getUrlMd5, urlMd5).eq(File::getStatus, FileStatus.SUCCESS).eq(File::getIsDelete, TableDelete.UN_DELETE)
.last("limit 1").one();
}
}

View File

@ -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>

View File

@ -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 {
}

View File

@ -1,5 +1,10 @@
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
@ -7,7 +12,43 @@ package cn.axzo.oss.integration.s3.base;
* @Version 0.0.1
**/
public interface BaseS3Service {
int RECORD_LIMIT = 100;
// ttl 15m; 60 * 15 = 900s
int DEFAULT_TTL_S = 900;
/**
* upload file
*/
boolean uploadByStream(InputStream srcStream, String tgtFileKey);
/**
* 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);
}

View File

@ -0,0 +1,15 @@
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();
}

View File

@ -0,0 +1,50 @@
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);
}
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,84 @@
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.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 boolean uploadByStream(InputStream srcStream, String tgtFileKey) {
return false;
}
/**
* 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;
}
}

View File

@ -1,6 +1,6 @@
package cn.axzo.oss.manager.api;
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
import cn.axzo.oss.dal.entity.File;
/**
* @Author admin
@ -10,5 +10,5 @@ import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
**/
public interface FileManager {
boolean delete(ServerFileDeleteDto dto);
boolean delete(File file);
}

View File

@ -0,0 +1,11 @@
package cn.axzo.oss.manager.api.dto.request;
/**
* @program: oss
* @description: 文件上传
* @author: mr.jie
* @date: 2021-07-29 18:31
**/
public class ServerFileUploadDto {
}

View File

@ -1,8 +1,8 @@
package cn.axzo.oss.manager.impl;
import cn.axzo.oss.dal.repository.FileDao;
import cn.axzo.oss.dal.entity.File;
import cn.axzo.oss.integration.s3.AliOssService;
import cn.axzo.oss.manager.api.FileManager;
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -17,8 +17,11 @@ import org.springframework.stereotype.Service;
@Slf4j
public class FileManagerImpl implements FileManager {
@Autowired
private AliOssService aliOssService;
@Override
public boolean delete(ServerFileDeleteDto dto) {
return Boolean.TRUE;
public boolean delete(File file) {
return aliOssService.delFile(file.getBucketName(), file.getFileUuid());
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.oss.service.impl;
import cn.axzo.oss.common.constans.CommonConstants.FileStatus;
import cn.axzo.oss.common.constans.CommonConstants.TableDelete;
import cn.axzo.oss.common.utils.JsonUtil;
import cn.axzo.oss.common.utils.Utility;
@ -22,14 +23,11 @@ import org.springframework.stereotype.Service;
@Slf4j
public class FileServiceImpl implements FileService {
private final FileManager fileManager;
@Autowired
private FileManager fileManager;
private final FileDao fileDao;
public FileServiceImpl(FileManager fileManager, FileDao fileDao) {
this.fileManager = fileManager;
this.fileDao = fileDao;
}
@Autowired
private FileDao fileDao;
/**
* 删除文件
@ -46,13 +44,14 @@ public class FileServiceImpl implements FileService {
log.info("delete urlMd5 = {}", urlMd5);
File file = fileDao.getFileByUrlMd5(urlMd5);
if (Utility.objIsNull(file)){
log.warn("delete file is null, urlMd5 = {}", urlMd5);
log.warn("delete file is null,url = {}, urlMd5 = {}", dto.getUrl(), urlMd5);
return;
}
boolean deleteFlag = fileManager.delete(dto);
boolean deleteFlag = fileManager.delete(file);
log.info("delete deleteFlag = {}", deleteFlag);
if (deleteFlag){
file.setIsDelete(TableDelete.DELETE);
file.setStatus(FileStatus.DELETED);
file.setUpdateBy(dto.getOperator());
file.setUpdateAt(null);
fileDao.updateById(file);

View File

@ -0,0 +1,28 @@
package cn.axzo.oss.test;
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
import cn.axzo.oss.service.api.FileService;
import cn.axzo.oss.test.base.SpringTestBase;
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-pro.oss-cn-hangzhou.aliyuncs.com/stable/face/19700101080046_6296.jpg");
dto.setOperator("zhangsan");
fileService.delete(dto);
}
}

View File

@ -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 {
}

View File

@ -38,6 +38,7 @@
<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>
@ -163,6 +164,11 @@
<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>