Merge branch 'feature/joint_log' into 'pre'

Feature/joint log

See merge request infra/oss!27
This commit is contained in:
田立勇 2022-12-08 11:38:55 +00:00
commit 3a6338766f
25 changed files with 579 additions and 202 deletions

View File

@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* OSS 启动类
@ -14,6 +15,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/
@Slf4j
@MapperScan(basePackages = {"cn.axzo.oss.dal.mapper"})
@EnableFeignClients(basePackages = {"cn.axzo.log.platform.client"})
@SpringBootApplication(scanBasePackages = {"cn.axzo.oss"})
public class Bootstrap {

View File

@ -1,6 +1,7 @@
package cn.axzo.oss.client.controller;
import cn.axzo.core.utils.converter.BeanConverter;
import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.oss.common.utils.BeanConvertUtil;
import cn.axzo.oss.http.api.ServerFileServiceApi;
import cn.axzo.oss.http.model.*;
@ -10,10 +11,12 @@ 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 cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
@ -30,18 +33,27 @@ public class ServerFileController implements ServerFileServiceApi {
@Autowired
private FileService fileService;
@Autowired
private HttpServletRequest httpServletRequest;
@Override
public CommonResponse<ServerFileUploadResponse> upload(@Valid @RequestBody ServerFileUploadRequest request) {
ServerFileUploadDto dto = BeanConvertUtil.copyBean(request, ServerFileUploadDto.class);
request.setFileContent(null);
return CommonResponse.success(BeanConverter.convert(fileService.upload(dto), ServerFileUploadResponse.class));
// 获取feign调用请求头携带的用户信息
String contextInfoLiteJsonStr = httpServletRequest.getHeader("X-CONTEXT-INFO-LITE");
ContextInfo.LiteSaasContext liteSaasContext = JSONUtil.toBean(contextInfoLiteJsonStr, ContextInfo.LiteSaasContext.class);
return CommonResponse.success(BeanConverter.convert(fileService.upload(dto, liteSaasContext), ServerFileUploadResponse.class));
}
@Override
public CommonResponse<FileInformationResponse> uploadV2(ServerFileUploadRequest request) {
public CommonResponse<FileInformationResponse> uploadV2(@Valid @RequestBody ServerFileUploadV2Request request) {
ServerFileUploadDto dto = BeanConvertUtil.copyBean(request, ServerFileUploadDto.class);
request.setFileContent(null);
return CommonResponse.success(BeanConverter.convert(fileService.uploadV2(dto), FileInformationResponse.class));
// 获取feign调用请求头携带的用户信息
String contextInfoLiteJsonStr = httpServletRequest.getHeader("X-CONTEXT-INFO-LITE");
ContextInfo.LiteSaasContext liteSaasContext = JSONUtil.toBean(contextInfoLiteJsonStr, ContextInfo.LiteSaasContext.class);
return CommonResponse.success(BeanConverter.convert(fileService.uploadV2(request.getServiceName(), dto, liteSaasContext), FileInformationResponse.class));
}
/**
@ -64,7 +76,7 @@ public class ServerFileController implements ServerFileServiceApi {
* @return
*/
@Override
public CommonResponse<List<FindFileUrlResponse>> getFileUrl(FindFileUrlRequest request) {
public CommonResponse<List<FindFileUrlResponse>> getFileUrl(@Valid @RequestBody FindFileUrlRequest request) {
FindFileUrlDto dto = BeanConvertUtil.copyBean(request, FindFileUrlDto.class);
return CommonResponse.success(BeanConverter.convert(fileService.findFileUrl(dto), FindFileUrlResponse.class));
}
@ -76,7 +88,7 @@ public class ServerFileController implements ServerFileServiceApi {
* @return
*/
@Override
public CommonResponse<List<FindFileKeyResponse>> getFileKey(FindFileKeyRequest request) {
public CommonResponse<List<FindFileKeyResponse>> getFileKey(@Valid @RequestBody FindFileKeyRequest request) {
FindFileKeyDto dto = BeanConvertUtil.copyBean(request, FindFileKeyDto.class);
return CommonResponse.success(BeanConverter.convert(fileService.findFileKey(dto), FindFileKeyResponse.class));
}

View File

@ -1,34 +1,49 @@
package cn.axzo.oss.client.controller;
import cn.axzo.core.utils.converter.BeanConverter;
import cn.axzo.framework.auth.annotation.PreBuildContext;
import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.framework.auth.domain.ContextInfoHolder;
import cn.axzo.oss.client.vo.FileInformationVo;
import cn.axzo.oss.client.vo.FindFileUrlVo;
import cn.axzo.oss.client.vo.WebFileUploadVo;
import cn.axzo.oss.common.exception.BizException;
import cn.axzo.oss.common.utils.BeanConvertUtil;
import cn.axzo.oss.manager.api.dto.request.FindFileUrlDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileDownloadDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto;
import cn.axzo.oss.manager.api.dto.response.FileInformationResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse;
import cn.axzo.oss.manager.api.dto.response.ServerFileDownloadResponse;
import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
import cn.axzo.oss.service.api.FileService;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import static cn.axzo.oss.common.enums.CodeEnum.FILE_NAME_TOO_LONG;
/**
* 前端文件controller
*
* @author zhangtianyu
* @date 2022/4/14 2:56 PM
**/
@PreBuildContext
@RestController
@RequestMapping("/webApi")
public class WebFileController {
private static int FILE_NAME_MAX_LENGTH = 128;
@Resource
private FileService fileService;
@ -38,44 +53,79 @@ public class WebFileController {
public CommonResponse<WebFileUploadVo> upload(@Valid @RequestParam String appCode,
@Valid @RequestParam String bizScene,
@Valid @RequestParam MultipartFile file) {
//获取用户信息
ContextInfo.LiteSaasContext liteSaasContext = null;
ContextInfo contextInfo = ContextInfoHolder.get();
if (contextInfo != null) {
liteSaasContext = contextInfo.lite();
}
String filename = file.getOriginalFilename();
BizException.error(filename.length() < FILE_NAME_MAX_LENGTH, FILE_NAME_TOO_LONG);
ServerFileUploadDto fileUploadDto = ServerFileUploadDto.builder()
.appCode(appCode)
.bizScene(bizScene)
.fileName(file.getOriginalFilename())
.fileName(filename)
.fileContent(file.getBytes())
.build();
ServerFileUploadResponse response = fileService.upload(fileUploadDto);
ServerFileUploadResponse response = fileService.upload(fileUploadDto, liteSaasContext);
WebFileUploadVo result = BeanConvertUtil.copyBean(response, WebFileUploadVo.class);
return CommonResponse.success(result);
}
@SneakyThrows
@PostMapping("/v1/file/getUrl")
@CrossOrigin
public CommonResponse<List<FindFileUrlVo>> getUrl(@Valid @RequestParam String appCode,
@Valid @RequestParam List<String> fileKey) {
FindFileUrlDto dto = FindFileUrlDto.builder()
.appCode(appCode)
.fileKey(fileKey)
.build();
List<FindFileUrlResponse> response = fileService.findFileUrl(dto);
return CommonResponse.success(BeanConverter.convert(response, FindFileUrlVo.class));
}
@PostMapping("/v2/file")
@CrossOrigin
@SneakyThrows
public CommonResponse<FileInformationVo> uploadV2(@Valid @RequestParam String appCode,
@Valid @RequestParam String bizScene,
@Valid @RequestParam MultipartFile file) {
@Valid @RequestParam String bizScene,
@Valid @RequestParam String serviceName,
@Valid @RequestParam MultipartFile file) {
//获取用户信息
ContextInfo.LiteSaasContext liteSaasContext = null;
ContextInfo contextInfo = ContextInfoHolder.get();
if (contextInfo != null) {
liteSaasContext = contextInfo.lite();
}
String filename = file.getOriginalFilename();
BizException.error(filename.length() < FILE_NAME_MAX_LENGTH, FILE_NAME_TOO_LONG);
ServerFileUploadDto fileUploadDto = ServerFileUploadDto.builder()
.appCode(appCode)
.bizScene(bizScene)
.fileName(file.getOriginalFilename())
.fileName(filename)
.fileContent(file.getBytes())
.build();
FileInformationResponse response = fileService.uploadV2(fileUploadDto);
FileInformationResponse response = fileService.uploadV2(serviceName, fileUploadDto, liteSaasContext);
FileInformationVo result = BeanConvertUtil.copyBean(response, FileInformationVo.class);
return CommonResponse.success(result);
}
@SneakyThrows
@PostMapping("/v1/file/getUrl")
@CrossOrigin
public CommonResponse<List<FindFileUrlVo>> getUrl(@Valid @RequestBody FindFileUrlDto dto) {
List<FindFileUrlResponse> response = fileService.findFileUrl(dto);
return CommonResponse.success(BeanConverter.convert(response, FindFileUrlVo.class));
}
@SneakyThrows
@GetMapping("/v1/file/download")
@CrossOrigin
public void download(@Valid @RequestParam String fileKey, HttpServletResponse response) {
ServerFileDownloadDto dto = ServerFileDownloadDto.builder()
.fileKey(fileKey)
.build();
ServerFileDownloadResponse result = fileService.download(dto);
InputStream inputStream = null;
OutputStream outputStream = response.getOutputStream();
try {
inputStream = result.getFileStream();
response.setContentType("application/x-download");
response.addHeader("Content-Disposition", "attachment;filename=" + result.getFileName() + "." + result.getFileFormat());
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
inputStream.close();
outputStream.close();
}
}
}

View File

@ -16,6 +16,10 @@
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-common</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-auth-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>

View File

@ -41,6 +41,7 @@ public enum CodeEnum implements EnumBase<Integer> {
FILE_FORMAT_NOT_SUPPORTED(109,"file format is not supported"),
FILE_UPLOAD_FAILED(109,"file upload failed"),
MISSING_REQUEST_PARAM(110, "missing request param"),
FILE_NAME_TOO_LONG(111, "file name too long max 128"),
;

View File

@ -23,7 +23,9 @@ public interface FileDao extends IService<File> {
*/
File getByAppCodeAndUrlMd5(String appCode, String urlMd5);
List<File> getByAppCodeAndFileUuids(String appCode, List<String> fileKey);
File getByFileUuid(String fileKey);
List<File> getByAppCodeAndUrlMd5s(String appCode, List<String> urlMd5List);
List<File> getByFileUuids(List<String> fileKey);
List<File> getByUrlMd5s(List<String> urlMd5List);
}

View File

@ -29,18 +29,25 @@ public class FileDaoImpl extends ServiceImpl<FileMapper, File> implements FileDa
}
@Override
public List<File> getByAppCodeAndFileUuids(String appCode, List<String> fileKey) {
return lambdaQuery().eq(File::getAppCode, appCode)
.in(File::getFileUuid, fileKey)
public File getByFileUuid(String fileKey) {
return lambdaQuery().eq(File::getFileUuid, fileKey)
.eq(File::getStatus, FileStatus.SUCCESS)
.eq(File::getIsDelete, TableDelete.UN_DELETED)
.last("limit 1")
.one();
}
@Override
public List<File> getByFileUuids(List<String> fileKey) {
return lambdaQuery().in(File::getFileUuid, fileKey)
.eq(File::getStatus, FileStatus.SUCCESS)
.eq(File::getIsDelete, TableDelete.UN_DELETED)
.list();
}
@Override
public List<File> getByAppCodeAndUrlMd5s(String appCode, List<String> urlMd5List) {
return lambdaQuery().eq(File::getAppCode, appCode)
.in(File::getUrlMd5, urlMd5List)
public List<File> getByUrlMd5s(List<String> urlMd5List) {
return lambdaQuery().in(File::getUrlMd5, urlMd5List)
.eq(File::getStatus, FileStatus.SUCCESS)
.eq(File::getIsDelete, TableDelete.UN_DELETED)
.list();

View File

@ -35,7 +35,7 @@ public interface ServerFileServiceApi {
* @return
*/
@RequestMapping(value = "/api/v2/server/upload", method = RequestMethod.POST)
CommonResponse<FileInformationResponse> uploadV2(ServerFileUploadRequest request);
CommonResponse<FileInformationResponse> uploadV2(ServerFileUploadV2Request request);
/**
* 删除文件

View File

@ -14,9 +14,6 @@ import java.util.List;
@Data
public class FindFileKeyRequest {
@NotBlank(message = "appCode must not be null")
private String appCode;
@NotNull(message = "url must not be null")
private List<String> url;
}

View File

@ -14,9 +14,6 @@ import java.util.List;
@Data
public class FindFileUrlRequest {
@NotBlank(message = "appCode must not be null")
private String appCode;
@NotNull(message = "fileKey must not be null")
private List<String> fileKey;
}

View File

@ -1,6 +1,7 @@
package cn.axzo.oss.http.model;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ -20,6 +21,7 @@ public class ServerFileUploadRequest {
@NotBlank(message = "bizScene must not be null")
private String bizScene;
@NotBlank(message = "fileName must not be null")
@Length(max = 128, message = "文件名不能超过128个字符")
private String fileName;
@NotNull(message = "fileContent must not be null")
private byte[] fileContent;

View File

@ -0,0 +1,28 @@
package cn.axzo.oss.http.model;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @Author: liyong.tian
* @Date: 2022/12/2 11:26
* @Description: 服务端文件上传请求类V2
*/
@Data
public class ServerFileUploadV2Request {
@NotBlank(message = "appCode must not be null")
private String appCode;
@NotBlank(message = "bizScene must not be null")
private String bizScene;
@NotBlank(message = "fileName must not be null")
@Length(max = 128, message = "文件名不能超过128个字符")
private String fileName;
@NotBlank(message = "serviceName must not be null")
private String serviceName;
@NotNull(message = "fileContent must not be null")
private byte[] fileContent;
}

View File

@ -1,9 +1,10 @@
package cn.axzo.oss.integration.s3.base;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import java.io.FilterInputStream;
import java.io.InputStream;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
/**
* @Author admin
@ -38,6 +39,8 @@ public interface BaseS3Service {
*/
ResponseEntity<byte[]> download(String tgtFileKey);
InputStream downloadFile(String bucket, String tgtFileKey);
/**
* get file address
*

View File

@ -6,6 +6,7 @@ import cn.azxo.framework.common.utils.LogUtil;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
@ -25,81 +26,88 @@ import java.io.InputStream;
@Slf4j
public class AliOssServiceImpl implements AliOssService {
@Autowired
private AliOssClient aliOssClient;
@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) {
LogUtil.error("uploadByStream OSSException", e);
return "";
} catch (ClientException e) {
LogUtil.error("uploadByStream ClientException", e);
return "";
/**
* 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) {
LogUtil.error("uploadByStream OSSException", e);
return "";
} catch (ClientException e) {
LogUtil.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();
}
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) {
LogUtil.error("ali oss delFile error = {}", e);
/**
* upload multi file
*/
@Override
public boolean uploadMultiFile(MultipartFile[] multipartFiles) {
return false;
}
return Boolean.FALSE;
}
/**
* download file
*/
@Override
public ResponseEntity<byte[]> download(String tgtFileKey) {
return null;
}
/**
* 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) {
LogUtil.error("ali oss delFile error = {}", e);
}
return Boolean.FALSE;
}
/**
* get file address
*
* @param ttl second
*/
@Override
public String getFileAddress(String tgtFileKey, int ttl) {
return null;
}
/**
* download file
*/
@Override
public ResponseEntity<byte[]> download(String tgtFileKey) {
return null;
}
/**
* get S3Object stream
*/
@Override
public FilterInputStream getS3ObjectStream(String tgtFileKey) {
return null;
}
@Override
public InputStream downloadFile(String bucket, String tgtFileKey) {
OSS client = aliOssClient.getClient();
OSSObject ossObject = client.getObject(bucket, tgtFileKey);
return ossObject.getObjectContent();
}
/**
* 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,5 +1,7 @@
package cn.axzo.oss.manager.api;
import java.io.InputStream;
/**
* @Author admin
* @Description
@ -8,22 +10,31 @@ package cn.axzo.oss.manager.api;
**/
public interface FileManager {
/**
* 删除文件
* @param bucketName 桶名称
* @param tgtFileKey 目标文件key
* @return
*/
boolean delete(String bucketName, String tgtFileKey);
/**
* 删除文件
*
* @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);
/**
* 上传
*
* @param bulkName
* @param keyPath
* @param fileContent
* @return
*/
String uploadByStream(String bulkName, String keyPath, byte[] fileContent);
/**
* 下载文件
*
* @param bucketName 桶名称
* @param tgtFileKey 目标文件key
*/
InputStream downloadFile(String bucketName, String tgtFileKey);
}

View File

@ -18,11 +18,6 @@ import java.util.List;
@AllArgsConstructor
public class FindFileKeyDto {
/**
* 应用码
*/
private String appCode;
/**
* 文件url
*/

View File

@ -18,11 +18,6 @@ import java.util.List;
@AllArgsConstructor
public class FindFileUrlDto {
/**
* 应用码
*/
private String appCode;
/**
* 文件uuid
*/

View File

@ -0,0 +1,23 @@
package cn.axzo.oss.manager.api.dto.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: liyong.tian
* @Date: 2022/11/29 15:42
* @Description: 文件下载
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ServerFileDownloadDto {
/**
* 文件uuid
*/
private String fileKey;
}

View File

@ -20,4 +20,13 @@ public class ServerFileUploadDto {
private String bizScene;
private String fileName;
private byte[] fileContent;
@Override
public String toString() {
return "ServerFileUploadDto{" +
"appCode='" + appCode + '\'' +
", bizScene='" + bizScene + '\'' +
", fileName='" + fileName + '\'' +
'}';
}
}

View File

@ -0,0 +1,48 @@
package cn.axzo.oss.manager.api.dto.response;
import lombok.Data;
import java.io.InputStream;
/**
* @Author: liyong.tian
* @Date: 2022/11/29 17:06
* @Description: 服务端文件下载响应类
*/
@Data
public class ServerFileDownloadResponse {
/**
* 文件 URL
*/
private String url;
/**
* 文件 Key
*/
private String fileKey;
/**
* URL MD5
*/
private String urlMd5;
/**
* 文件名称
*/
private String fileName;
/**
* 文件大小
*/
private Long fileSize;
/**
* 文件格式
*/
private String fileFormat;
/**
* 文件流
*/
private InputStream fileStream;
}

View File

@ -2,12 +2,13 @@ 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;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* @Author admin
* @Description
@ -18,29 +19,35 @@ import org.springframework.stereotype.Service;
@Slf4j
public class FileManagerImpl implements FileManager {
@Autowired
private AliOssService aliOssService;
@Autowired
private AliOssService aliOssService;
/**
* 删除文件
* @param bucketName 桶名称
* @param tgtFileKey 目标文件key
* @return
*/
@Override
public boolean delete(String bucketName, String tgtFileKey) {
return aliOssService.delFile(bucketName, tgtFileKey);
}
/**
* 删除文件
*
* @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) {
/**
* @param bulkName 默认的取值为
* @param keyPath key的前置路径
*/
public String uploadByStream(String bulkName, String keyPath, byte[] fileContent) {
InputStream inputStream = new ByteArrayInputStream(fileContent);
InputStream inputStream = new ByteArrayInputStream(fileContent);
return aliOssService.uploadByStream(bulkName, keyPath, inputStream);
}
return aliOssService.uploadByStream(bulkName, keyPath, inputStream);
}
@Override
public InputStream downloadFile(String bucketName, String tgtFileKey) {
return aliOssService.downloadFile(bucketName, tgtFileKey);
}
}

View File

@ -22,6 +22,10 @@
<groupId>cn.axzo.oss</groupId>
<artifactId>oss-manager-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.platform</groupId>
<artifactId>axzo-log-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,13 +1,8 @@
package cn.axzo.oss.service.api;
import cn.axzo.oss.manager.api.dto.request.FindFileKeyDto;
import cn.axzo.oss.manager.api.dto.request.FindFileUrlDto;
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.FileInformationResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileKeyResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse;
import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.oss.manager.api.dto.request.*;
import cn.axzo.oss.manager.api.dto.response.*;
import java.util.List;
@ -31,11 +26,13 @@ public interface FileService {
*
* @param request
*/
ServerFileUploadResponse upload(ServerFileUploadDto request);
ServerFileUploadResponse upload(ServerFileUploadDto request, ContextInfo.LiteSaasContext liteSaasContext);
List<FindFileUrlResponse> findFileUrl(FindFileUrlDto dto);
List<FindFileKeyResponse> findFileKey(FindFileKeyDto dto);
FileInformationResponse uploadV2(ServerFileUploadDto request);
FileInformationResponse uploadV2(String serviceName, ServerFileUploadDto request, ContextInfo.LiteSaasContext liteSaasContext);
ServerFileDownloadResponse download(ServerFileDownloadDto dto);
}

View File

@ -1,5 +1,8 @@
package cn.axzo.oss.service.impl;
import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.log.platform.client.LogPlatClient;
import cn.axzo.log.platform.client.model.OperateLogReq;
import cn.axzo.oss.common.constans.CommonConstants;
import cn.axzo.oss.common.constans.CommonConstants.FileStatus;
import cn.axzo.oss.common.constans.CommonConstants.TableDelete;
@ -16,23 +19,23 @@ 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.FindFileKeyDto;
import cn.axzo.oss.manager.api.dto.request.FindFileUrlDto;
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.FileInformationResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileKeyResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse;
import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
import cn.axzo.oss.manager.api.dto.request.*;
import cn.axzo.oss.manager.api.dto.response.*;
import cn.axzo.oss.service.api.FileService;
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
@ -45,6 +48,15 @@ import java.util.stream.Collectors;
@Slf4j
public class FileServiceImpl implements FileService {
private static String FILE_UPLOAD_CODE = "OSS_FILE_UPLOAD";
private static String FILE_UPLOAD_NAME = "文件上传";
private static String APPCODE_FACE = "face";
private static String SCENE_FACE = "face";
private static String APPCODE_IDCARD = "idcard";
private static String SCENE_IDCARD = "idcard";
private static String APPCODE_BANKCARD = "bankcard";
private static String SCENE_BANKCARD = "bankcard";
@Autowired
private FileManager fileManager;
@ -60,6 +72,11 @@ public class FileServiceImpl implements FileService {
@Autowired
private FileUploadConfigManager fileUploadConfigManager;
@Autowired
private Environment environment;
@Autowired
private LogPlatClient logPlatClient;
/**
* 删除文件
@ -113,17 +130,75 @@ public class FileServiceImpl implements FileService {
* @param dto
*/
@Override
public ServerFileUploadResponse upload(ServerFileUploadDto dto) {
public ServerFileUploadResponse upload(ServerFileUploadDto dto, ContextInfo.LiteSaasContext liteSaasContext) {
File ossFile = uploadFileAndGetFile(dto);
//操作日志记录
operateLog(dto.toString(), "", FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
return setResponse(ossFile);
}
@Override
public FileInformationResponse uploadV2(ServerFileUploadDto request) {
public FileInformationResponse uploadV2(String serviceName, ServerFileUploadDto request, ContextInfo.LiteSaasContext liteSaasContext) {
File ossFile = uploadFileAndGetFile(request);
//操作日志记录
operateLog(request.toString(), serviceName, FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
return setFileInfoResp(ossFile);
}
@Override
public ServerFileDownloadResponse download(ServerFileDownloadDto dto) {
log.info("file download dto = {}", JsonUtil.obj2Str(dto));
File file = fileDao.getByFileUuid(dto.getFileKey());
if (Utility.objIsNull(file)) {
log.warn("file download is null, fileKey = {}", dto.getFileKey());
return null;
}
String tgtFileKey = Utility
.generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat());
log.info("file download tgtFileKey = {}", tgtFileKey);
InputStream fileStream = fileManager.downloadFile(file.getBucketName(), tgtFileKey);
return setFileDownloadResponse(file, fileStream);
}
private ServerFileDownloadResponse setFileDownloadResponse(File file, InputStream fileStream) {
ServerFileDownloadResponse resp = new ServerFileDownloadResponse();
resp.setUrl(file.getFileUrl());
resp.setFileName(file.getFileName());
resp.setUrlMd5(file.getUrlMd5());
resp.setFileKey(file.getFileUuid());
resp.setFileFormat(file.getFileFormat());
resp.setFileStream(fileStream);
return resp;
}
/**
* 操作日志记录
*/
private void operateLog(String param, String serviceName, String featureCode, String featureName, ContextInfo.LiteSaasContext liteSaasContext) {
if (liteSaasContext == null || liteSaasContext.getIdentityId() == null || liteSaasContext.getIdentityType() == null) {
log.warn("获取用户上下文信息失败");
return;
}
//记录日志
try {
OperateLogReq log = OperateLogReq.builder()
.serviceName(StringUtils.isNotEmpty(serviceName) ? serviceName : environment.getProperty("spring.application.name"))
.featureCode(featureCode)
.featureName(featureName)
.operateTime(new Date())
.identityId(liteSaasContext.getIdentityId())
.identityType(liteSaasContext.getIdentityType())
.operateParam(param)
.workspaceId(liteSaasContext.getWorkspaceId())
.operateType(1)
.build();
logPlatClient.createOperateLog(log);
} catch (Exception e) {
log.warn("服务间调用异常-发送日志失败: errMsg={}.", e.getMessage());
}
}
private File uploadFileAndGetFile(ServerFileUploadDto dto) {
log.info("update fileName:{},appCode:{},bizScene:{}",
dto.getFileName(), dto.getAppCode(), dto.getBizScene());
@ -147,38 +222,121 @@ public class FileServiceImpl implements FileService {
@Override
public List<FindFileUrlResponse> findFileUrl(FindFileUrlDto dto) {
log.info("find file url dto = {}", JsonUtil.obj2Str(dto));
// 检查app code
checkAppCode(dto.getAppCode());
List<File> fileList = fileDao.getByAppCodeAndFileUuids(dto.getAppCode(), dto.getFileKey());
// 做兼容处理如果List<String> fileKey如果存在url取出url不做查询处理
List<String> urlList = new ArrayList<>();
List<String> fileKeyList = new ArrayList<>();
for (String fileKey : dto.getFileKey()) {
if (fileKey.contains("http")) {
urlList.add(fileKey);
} else {
fileKeyList.add(fileKey);
}
}
List<File> fileList = fileDao.getByFileUuids(fileKeyList);
if (CollectionUtil.isEmpty(fileList)) {
log.warn("find file url is null,key = {}", Arrays.toString(dto.getFileKey().toArray()));
return new ArrayList<>();
}
return setFileUrlRes(fileList);
return setFileUrlRes(urlList, fileList);
}
@Override
public List<FindFileKeyResponse> findFileKey(FindFileKeyDto dto) {
log.info("find file key dto = {}", JsonUtil.obj2Str(dto));
// 检查app code
checkAppCode(dto.getAppCode());
List<String> urlMd5List = dto.getUrl().stream()
List<String> urlList = dto.getUrl();
List<String> urlMd5List = urlList.stream()
.map(url -> Utility.getMd5(url))
.collect(Collectors.toList());
List<File> fileList = fileDao.getByAppCodeAndUrlMd5s(dto.getAppCode(), urlMd5List);
if (CollectionUtil.isEmpty(fileList)) {
log.warn("find file key is null,url = {}", Arrays.toString(dto.getUrl().toArray()));
return new ArrayList<>();
List<File> fileList = fileDao.getByUrlMd5s(urlMd5List);
//处理app端历史数据不在file表中的情况
if (urlMd5List.size() > fileList.size()) {
List<String> existUrlList = fileList.stream().map(File::getFileUrl).collect(Collectors.toList());
urlList.removeAll(existUrlList);
List<FindFileKeyResponse> resList = setFileKeyResByUrl(urlList);
// 异步新增file数据
asyncSaveFile(resList);
return resList;
}
return setFileKeyRes(fileList);
return setFileKeyResByFile(fileList);
}
private List<FindFileUrlResponse> setFileUrlRes(List<File> fileList) {
private void asyncSaveFile(List<FindFileKeyResponse> resList) {
List<CompletableFuture<Void>> completableFutures = new ArrayList<>(resList.size() / 10 + 1);
Lists.partition(resList, 10)
.forEach(findFileKeyResponses -> completableFutures.add(CompletableFuture.runAsync(
() -> findFileKeyResponses.forEach(response -> saveFile(response))
)));
}
private File saveFile(FindFileKeyResponse response) {
String url = response.getUrl();
String appCode = "", bizScene = "";
if (url.contains(APPCODE_FACE)) {
appCode = APPCODE_FACE;
bizScene = SCENE_FACE;
} else if(url.contains(APPCODE_IDCARD)) {
appCode = APPCODE_IDCARD;
bizScene = SCENE_IDCARD;
} else if(url.contains(APPCODE_BANKCARD)) {
appCode = APPCODE_BANKCARD;
bizScene = SCENE_BANKCARD;
}
if (StringUtils.isEmpty(appCode) || StringUtils.isEmpty(bizScene)) {
throw new BizException(CodeEnum.APP_CODE_NOT_FOUND);
}
// 通过appcode获取文件渠道桶信息
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode);
// 通过渠道桶编码获取到具体文件业务场景
FileBusinessScene scene = fileBusinessSceneManager
.getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), bizScene);
// 通过渠道码和桶名称获取获取指定上传配置
FileUploadConfig fileUploadConfig = fileUploadConfigManager
.getByUploadConfig(scene.getAppChannelBucketNo(), scene.getDirectory());
//获取文件名和文件格式
int dotIndexOf = url.lastIndexOf(FileClassEnum.DOT.type);
int nameIndexOf = url.lastIndexOf(FileClassEnum.SEPARATOR_CHAR.type);
String fileFormat = url.substring(dotIndexOf + CommonConstants.ONE).toLowerCase();
String fileName = url.substring(nameIndexOf + CommonConstants.ONE, dotIndexOf);
File ossFile = new File();
ossFile.setAppCode(appCode);
ossFile.setAppChannelBucketNo(fileUploadConfig.getAppChannelBucketNo());
ossFile.setAppCode(fileUploadConfig.getAppCode());
ossFile.setChannelCode(fileUploadConfig.getChannelCode());
ossFile.setBucketName(fileUploadConfig.getBucketName());
ossFile.setDirectory(fileUploadConfig.getDirectory());
ossFile.setFileFormat(fileFormat);
ossFile.setFileUuid(response.getFileKey());
ossFile.setFileUrl(response.getUrl());
ossFile.setUrlMd5(response.getFileKey());
ossFile.setStorageUnit(fileUploadConfig.getStorageUnit());
ossFile.setStorageSize(fileUploadConfig.getStorageSize());
ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_SUCCESS.getCode());
ossFile.setFileName(fileName);
fileDao.save(ossFile);
return ossFile;
}
private List<FindFileUrlResponse> setFileUrlRes(List<String> urlList, List<File> fileList) {
List<FindFileUrlResponse> resList = new ArrayList<>();
fileList.forEach(file -> {
if (CollectionUtil.isNotEmpty(urlList)) {
urlList.stream().forEach(url -> {
FindFileUrlResponse response = new FindFileUrlResponse();
response.setUrl(url);
response.setFileKey(url);
resList.add(response);
});
}
fileList.stream().forEach(file -> {
FindFileUrlResponse response = new FindFileUrlResponse();
response.setUrl(file.getFileUrl());
response.setFileKey(file.getFileUuid());
@ -187,7 +345,18 @@ public class FileServiceImpl implements FileService {
return resList;
}
private List<FindFileKeyResponse> setFileKeyRes(List<File> fileList) {
private List<FindFileKeyResponse> setFileKeyResByUrl(List<String> urlList) {
List<FindFileKeyResponse> resList = new ArrayList<>();
urlList.stream().forEach(url -> {
FindFileKeyResponse response = new FindFileKeyResponse();
response.setUrl(url);
response.setFileKey(Utility.getUUID());
resList.add(response);
});
return resList;
}
private List<FindFileKeyResponse> setFileKeyResByFile(List<File> fileList) {
List<FindFileKeyResponse> resList = new ArrayList<>();
fileList.forEach(file -> {
FindFileKeyResponse response = new FindFileKeyResponse();
@ -270,13 +439,13 @@ public class FileServiceImpl implements FileService {
return response;
}
private FileInformationResponse setFileInfoResp(File ossFile){
FileInformationResponse resp=new FileInformationResponse();
resp.setUrl(ossFile.getFileUrl());
resp.setFileName(ossFile.getFileName());
resp.setUrlMd5(ossFile.getUrlMd5());
resp.setFileKey(ossFile.getFileUuid());
return resp;
}
private FileInformationResponse setFileInfoResp(File ossFile) {
FileInformationResponse resp = new FileInformationResponse();
resp.setUrl(ossFile.getFileUrl());
resp.setFileName(ossFile.getFileName());
resp.setUrlMd5(ossFile.getUrlMd5());
resp.setFileKey(ossFile.getFileUuid());
return resp;
}
}

View File

@ -20,6 +20,7 @@
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
<aliyun-oss.version>3.10.2</aliyun-oss.version>
<axzo-log-api.version>1.0.0-SNAPSHOT</axzo-log-api.version>
</properties>
<modules>
@ -95,6 +96,11 @@
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-oss.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.platform</groupId>
<artifactId>axzo-log-api</artifactId>
<version>${axzo-log-api.version}</version>
</dependency>
</dependencies>
</dependencyManagement>