Merge branch 'feature/joint_log' into 'master'
Feature/joint log See merge request infra/oss!60
This commit is contained in:
commit
3fa654e71f
@ -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 {
|
||||
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -1,25 +1,38 @@
|
||||
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;
|
||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
|
||||
/**
|
||||
* 前端文件controller
|
||||
*
|
||||
@ -29,53 +42,90 @@ import java.util.List;
|
||||
@RestController
|
||||
@RequestMapping("/webApi")
|
||||
public class WebFileController {
|
||||
|
||||
private static int FILE_NAME_MAX_LENGTH = 128;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@SneakyThrows
|
||||
@PostMapping("/v1/file")
|
||||
@PostMapping(value = "/v1/file", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
@CrossOrigin
|
||||
public CommonResponse<WebFileUploadVo> upload(@Valid @RequestParam String appCode,
|
||||
@Valid @RequestParam String bizScene,
|
||||
@Valid @RequestParam MultipartFile file) {
|
||||
public CommonResponse<WebFileUploadVo> upload(@Valid @RequestParam("appCode") String appCode,
|
||||
@Valid @RequestParam("bizScene") String bizScene,
|
||||
@Valid @RequestPart 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);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/v2/file", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
@CrossOrigin
|
||||
@SneakyThrows
|
||||
@PreBuildContext
|
||||
public CommonResponse<FileInformationVo> uploadV2(@Valid @RequestParam("appCode") String appCode,
|
||||
@Valid @RequestParam("bizScene") String bizScene,
|
||||
@Valid @RequestParam("serviceName") String serviceName,
|
||||
@Valid @RequestPart 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(filename)
|
||||
.fileContent(file.getBytes())
|
||||
.build();
|
||||
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 @RequestParam String appCode,
|
||||
@Valid @RequestParam List<String> fileKey) {
|
||||
FindFileUrlDto dto = FindFileUrlDto.builder()
|
||||
.appCode(appCode)
|
||||
.fileKey(fileKey)
|
||||
.build();
|
||||
@PreBuildContext
|
||||
public CommonResponse<List<FindFileUrlVo>> getUrl(@Valid @RequestBody FindFileUrlDto dto) {
|
||||
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) {
|
||||
ServerFileUploadDto fileUploadDto = ServerFileUploadDto.builder()
|
||||
.appCode(appCode)
|
||||
.bizScene(bizScene)
|
||||
.fileName(file.getOriginalFilename())
|
||||
.fileContent(file.getBytes())
|
||||
.build();
|
||||
FileInformationResponse response = fileService.uploadV2(fileUploadDto);
|
||||
FileInformationVo result = BeanConvertUtil.copyBean(response, FileInformationVo.class);
|
||||
return CommonResponse.success(result);
|
||||
@GetMapping("/v1/file/download")
|
||||
@CrossOrigin
|
||||
public void download(@Valid ServerFileDownloadDto dto, HttpServletResponse response) {
|
||||
ServerFileDownloadResponse result = fileService.download(dto);
|
||||
InputStream inputStream = null;
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
try {
|
||||
inputStream = result.getFileStream();
|
||||
response.setContentType("image/jpg");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.addHeader("Content-Disposition", "attachment;filename=" + result.getFileName() + "." + result.getFileFormat());
|
||||
IOUtils.copy(inputStream, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -18,7 +18,10 @@ public abstract class CommonConstants {
|
||||
*/
|
||||
public static final int ONE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* app端oss bucketName:axzo-pro
|
||||
*/
|
||||
public static final String APP_PRO_BUCKET_NAME = "axzo-pro";
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
|
||||
@ -41,6 +41,9 @@ 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"),
|
||||
|
||||
FILE_NOT_FOUND(112, "file not found"),
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -23,7 +23,11 @@ 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);
|
||||
|
||||
File getByUrlMd5(String urlMd5);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ 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;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@ -29,20 +30,36 @@ 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> fileKeys) {
|
||||
return lambdaQuery().in(CollectionUtil.isNotEmpty(fileKeys), File::getFileUuid, fileKeys)
|
||||
.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> urlMd5s) {
|
||||
return lambdaQuery().in(CollectionUtil.isNotEmpty(urlMd5s), File::getUrlMd5, urlMd5s)
|
||||
.eq(File::getStatus, FileStatus.SUCCESS)
|
||||
.eq(File::getIsDelete, TableDelete.UN_DELETED)
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getByUrlMd5(String urlMd5) {
|
||||
return lambdaQuery().eq(File::getUrlMd5, urlMd5)
|
||||
.eq(File::getStatus, FileStatus.SUCCESS)
|
||||
.eq(File::getIsDelete, TableDelete.UN_DELETED)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -20,7 +21,7 @@ public interface BaseS3Service {
|
||||
/**
|
||||
* upload file
|
||||
*/
|
||||
String uploadByStream(String bucketName, String tgtFileKey, InputStream srcStream);
|
||||
String uploadByStream(String bucketName, String tgtFileKey, String fileName, InputStream srcStream);
|
||||
|
||||
/**
|
||||
* upload multi file
|
||||
@ -38,6 +39,8 @@ public interface BaseS3Service {
|
||||
*/
|
||||
ResponseEntity<byte[]> download(String tgtFileKey);
|
||||
|
||||
InputStream downloadFile(String bucket, String tgtFileKey, String style);
|
||||
|
||||
/**
|
||||
* get file address
|
||||
*
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
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.azxo.framework.common.utils.LogUtil;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @program: oss
|
||||
* @description: 阿里云服务客户端(用于兼容app端阿里云oss accessKeyId和secretAccessKey)
|
||||
* @author: mr.jie
|
||||
* @date: 2021-07-29 15:49
|
||||
**/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AliOssAppProClient implements OssClientBase {
|
||||
|
||||
private static final String APP_PRO_ACCESS_KEY_ID = "LTAI4GHX7wnnpcp94Vu7JGGs";
|
||||
private static final String APP_PRO_ACCESS_KEY_SECRET = "8X5njFjCuUq1XNKkrz1rLV9xv1Mj3J";
|
||||
private static final String APP_PRO_ENDPOINT = "https://oss-cn-hangzhou.aliyuncs.com";
|
||||
|
||||
private volatile static OSS instance = null;
|
||||
|
||||
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 = {}", APP_PRO_ENDPOINT, APP_PRO_ACCESS_KEY_ID, APP_PRO_ACCESS_KEY_SECRET);
|
||||
try {
|
||||
instance = new OSSClientBuilder().build(APP_PRO_ENDPOINT, APP_PRO_ACCESS_KEY_ID, APP_PRO_ACCESS_KEY_SECRET);
|
||||
} catch (Exception e) {
|
||||
instance = null;
|
||||
LogUtil.error("initClient error = {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpoint() {
|
||||
return APP_PRO_ENDPOINT;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,12 +1,16 @@
|
||||
package cn.axzo.oss.integration.s3.impl;
|
||||
|
||||
import cn.axzo.oss.integration.s3.AliOssService;
|
||||
import cn.axzo.oss.integration.s3.client.AliOssAppProClient;
|
||||
import cn.axzo.oss.integration.s3.client.AliOssClient;
|
||||
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.GetObjectRequest;
|
||||
import com.aliyun.oss.model.OSSObject;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -14,6 +18,9 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
|
||||
|
||||
/**
|
||||
* @program: oss
|
||||
@ -25,81 +32,107 @@ 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 "";
|
||||
@Autowired
|
||||
private AliOssAppProClient aliOssAppProClient;
|
||||
|
||||
/**
|
||||
* upload file
|
||||
*/
|
||||
@Override
|
||||
public String uploadByStream(String bucketName, String tgtFileKey, String fileName, InputStream srcStream) {
|
||||
OSS client = aliOssClient.getClient();
|
||||
try {
|
||||
// 创建上传文件的元信息,通过文件云信息设置HTTP Header
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
// 设置内容被下载时的名称
|
||||
metadata.setContentDisposition("attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
|
||||
metadata.setContentEncoding("utf-8");
|
||||
client.putObject(bucketName, tgtFileKey, srcStream, metadata);
|
||||
} catch (OSSException e) {
|
||||
LogUtil.error("uploadByStream OSSException", e);
|
||||
return "";
|
||||
} catch (Exception 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 {
|
||||
OSS client = aliOssClient.getClient();
|
||||
if (bucket.contains(APP_PRO_BUCKET_NAME)) {
|
||||
client = aliOssAppProClient.getClient();
|
||||
}
|
||||
client.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, String style) {
|
||||
OSS client = aliOssClient.getClient();
|
||||
if (bucket.contains(APP_PRO_BUCKET_NAME)) {
|
||||
client = aliOssAppProClient.getClient();
|
||||
}
|
||||
GetObjectRequest request = new GetObjectRequest(bucket, tgtFileKey);
|
||||
if (StringUtils.isNotEmpty(style)) {
|
||||
request.setProcess(style);
|
||||
}
|
||||
OSSObject ossObject = client.getObject(request);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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, String fileName, byte[] fileContent);
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param tgtFileKey 目标文件key
|
||||
*/
|
||||
InputStream downloadFile(String bucketName, String tgtFileKey, String style);
|
||||
|
||||
}
|
||||
|
||||
@ -18,11 +18,6 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class FindFileKeyDto {
|
||||
|
||||
/**
|
||||
* 应用码
|
||||
*/
|
||||
private String appCode;
|
||||
|
||||
/**
|
||||
* 文件url
|
||||
*/
|
||||
|
||||
@ -5,6 +5,7 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -18,13 +19,9 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class FindFileUrlDto {
|
||||
|
||||
/**
|
||||
* 应用码
|
||||
*/
|
||||
private String appCode;
|
||||
|
||||
/**
|
||||
* 文件uuid
|
||||
*/
|
||||
@NotNull
|
||||
private List<String> fileKey;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.oss.manager.api.dto.request;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @Author: liyong.tian
|
||||
* @Date: 2022/11/29 15:42
|
||||
* @Description: 文件下载
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ServerFileDownloadDto {
|
||||
|
||||
/**
|
||||
* 文件uuid
|
||||
*/
|
||||
@NotBlank
|
||||
private String fileKey;
|
||||
|
||||
/**
|
||||
* 图片样式
|
||||
*/
|
||||
private String style;
|
||||
}
|
||||
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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, String fileName, byte[] fileContent) {
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(fileContent);
|
||||
InputStream inputStream = new ByteArrayInputStream(fileContent);
|
||||
|
||||
return aliOssService.uploadByStream(bulkName, keyPath, inputStream);
|
||||
}
|
||||
return aliOssService.uploadByStream(bulkName, keyPath, fileName, inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream downloadFile(String bucketName, String tgtFileKey, String style) {
|
||||
return aliOssService.downloadFile(bucketName, tgtFileKey, style);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,25 +19,24 @@ 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.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
|
||||
|
||||
/**
|
||||
* @Author admin
|
||||
* @Description
|
||||
@ -45,6 +47,13 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
public class FileServiceImpl implements FileService {
|
||||
|
||||
private static final String FILE_UPLOAD_CODE = "OSS_FILE_UPLOAD";
|
||||
private static final String FILE_UPLOAD_NAME = "文件上传";
|
||||
|
||||
private static final String IS_URL = "https://";
|
||||
|
||||
private static final String HTTP_COM = ".com/";
|
||||
|
||||
@Autowired
|
||||
private FileManager fileManager;
|
||||
|
||||
@ -60,6 +69,11 @@ public class FileServiceImpl implements FileService {
|
||||
@Autowired
|
||||
private FileUploadConfigManager fileUploadConfigManager;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
private LogPlatClient logPlatClient;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
@ -80,10 +94,16 @@ public class FileServiceImpl implements FileService {
|
||||
log.warn("delete file is null,url = {}, urlMd5 = {}", dto.getUrl(), urlMd5);
|
||||
return;
|
||||
}
|
||||
String tgtFileKey = Utility
|
||||
.generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat());
|
||||
//String tgtFileKey = Utility.generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat());
|
||||
//兼容app端oss历史上传文件的url处理
|
||||
String tgtFileKey = file.getFileUrl().substring(file.getFileUrl().indexOf(HTTP_COM) + 5);
|
||||
log.debug("delete tgtFileKey = {}", tgtFileKey);
|
||||
boolean deleteFlag = fileManager.delete(file.getBucketName(), tgtFileKey);
|
||||
String bucketName = file.getBucketName();
|
||||
if (file.getFileUrl().contains(APP_PRO_BUCKET_NAME)) {
|
||||
//兼容处理,支持app端bucketName:axzo-pro
|
||||
bucketName = APP_PRO_BUCKET_NAME;
|
||||
}
|
||||
boolean deleteFlag = fileManager.delete(bucketName, tgtFileKey);
|
||||
log.info("delete deleteFlag = {}", deleteFlag);
|
||||
if (deleteFlag) {
|
||||
File updateFile = new File();
|
||||
@ -113,17 +133,87 @@ 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 = null;
|
||||
String fileKey = dto.getFileKey();
|
||||
if (fileKey.contains(IS_URL)) {
|
||||
String urlMd5 = Utility.getMd5(fileKey);
|
||||
file = fileDao.getByUrlMd5(urlMd5);
|
||||
} else {
|
||||
file = fileDao.getByFileUuid(fileKey);
|
||||
}
|
||||
if (Utility.objIsNull(file)) {
|
||||
log.warn("file download is null, fileKey = {}", fileKey);
|
||||
BizException.error(Utility.objIsNotNull(file), CodeEnum.FILE_NOT_FOUND);
|
||||
}
|
||||
//String tgtFileKey = Utility.generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat());
|
||||
//兼容app端oss历史上传文件的url处理
|
||||
String tgtFileKey = file.getFileUrl().substring(file.getFileUrl().indexOf(HTTP_COM) + 5);
|
||||
log.info("file download tgtFileKey = {}", tgtFileKey);
|
||||
String bucketName = file.getBucketName();
|
||||
if (file.getFileUrl().contains(APP_PRO_BUCKET_NAME)) {
|
||||
//兼容处理,支持app端bucketName:axzo-pro
|
||||
bucketName = APP_PRO_BUCKET_NAME;
|
||||
}
|
||||
InputStream fileStream = fileManager.downloadFile(bucketName, tgtFileKey, dto.getStyle());
|
||||
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,52 +237,195 @@ 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());
|
||||
if (CollectionUtil.isEmpty(fileList)) {
|
||||
log.warn("find file url is null,key = {}", Arrays.toString(dto.getFileKey().toArray()));
|
||||
return new ArrayList<>();
|
||||
// 做兼容处理,如果List<String> fileKey如果存在url取出url,不做查询处理
|
||||
List<String> urlList = new ArrayList<>();
|
||||
List<String> fileKeyList = new ArrayList<>();
|
||||
Map<String, String> fileKeyStyleMap = new HashMap<>();
|
||||
for (String fileKey : dto.getFileKey()) {
|
||||
if (fileKey.contains(IS_URL)) {
|
||||
urlList.add(fileKey);
|
||||
} else {
|
||||
//对fileKey带图片样式进行处理
|
||||
if (fileKey.contains("?")) {
|
||||
String[] fileKeyArr = fileKey.split("\\?");
|
||||
fileKeyList.add(fileKeyArr[0]);
|
||||
fileKeyStyleMap.put(fileKeyArr[0], fileKey);
|
||||
} else {
|
||||
fileKeyList.add(fileKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
return setFileUrlRes(fileList);
|
||||
List<File> fileList = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(fileKeyList)) {
|
||||
fileList = fileDao.getByFileUuids(fileKeyList);
|
||||
}
|
||||
return setFileUrlRes(urlList, fileKeyStyleMap, fileList);
|
||||
}
|
||||
|
||||
private List<FindFileUrlResponse> setFileUrlRes(List<String> urlList) {
|
||||
List<FindFileUrlResponse> resList = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(urlList)) {
|
||||
urlList.stream().forEach(url -> {
|
||||
FindFileUrlResponse response = new FindFileUrlResponse();
|
||||
response.setUrl(url);
|
||||
response.setFileKey(url);
|
||||
resList.add(response);
|
||||
});
|
||||
}
|
||||
return resList;
|
||||
}
|
||||
|
||||
private List<FindFileUrlResponse> setFileUrlRes(List<String> urlList, Map<String, String> fileKeyStyleMap, List<File> fileList) {
|
||||
List<FindFileUrlResponse> resList = setFileUrlRes(urlList);
|
||||
|
||||
if (CollectionUtil.isNotEmpty(fileList)) {
|
||||
fileList.stream().forEach(file -> {
|
||||
FindFileUrlResponse response = new FindFileUrlResponse();
|
||||
String fileUrl = file.getFileUrl();
|
||||
String fileKey = file.getFileUuid();
|
||||
if (fileKeyStyleMap.containsKey(fileKey)) {
|
||||
fileKey = fileKeyStyleMap.get(fileKey);
|
||||
fileUrl += fileKey.substring(fileKey.indexOf("?"));
|
||||
}
|
||||
response.setFileKey(fileKey);
|
||||
response.setUrl(fileUrl);
|
||||
resList.add(response);
|
||||
});
|
||||
}
|
||||
return resList;
|
||||
}
|
||||
|
||||
@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()
|
||||
.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<>();
|
||||
}
|
||||
return setFileKeyRes(fileList);
|
||||
}
|
||||
|
||||
private List<FindFileUrlResponse> setFileUrlRes(List<File> fileList) {
|
||||
List<FindFileUrlResponse> resList = new ArrayList<>();
|
||||
fileList.forEach(file -> {
|
||||
FindFileUrlResponse response = new FindFileUrlResponse();
|
||||
response.setUrl(file.getFileUrl());
|
||||
response.setFileKey(file.getFileUuid());
|
||||
resList.add(response);
|
||||
List<String> urlList = dto.getUrl();
|
||||
//用于对请求参数中为fileKey的兼容处理
|
||||
List<String> fileKeyList = new ArrayList<>();
|
||||
List<String> urlMd5List = new ArrayList<>();
|
||||
urlList.stream().forEach(url -> {
|
||||
if (url.contains(IS_URL)) {
|
||||
urlMd5List.add(Utility.getMd5(url));
|
||||
} else {
|
||||
fileKeyList.add(url);
|
||||
}
|
||||
});
|
||||
List<File> fileList = new ArrayList<>();
|
||||
List<FindFileKeyResponse> resList = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(urlMd5List)) {
|
||||
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);
|
||||
resList = setFileKeyResByUrl(urlList);
|
||||
// 异步新增file数据
|
||||
asyncSaveFile(resList);
|
||||
}
|
||||
}
|
||||
resList.addAll(setFileKeyRes(fileKeyList, fileList));
|
||||
return resList;
|
||||
}
|
||||
|
||||
private List<FindFileKeyResponse> setFileKeyRes(List<File> fileList) {
|
||||
private List<FindFileKeyResponse> setFileKeyRes(List<String> fileKeyList, List<File> fileList) {
|
||||
List<FindFileKeyResponse> resList = new ArrayList<>();
|
||||
fileList.forEach(file -> {
|
||||
if (CollectionUtil.isNotEmpty(fileKeyList)) {
|
||||
fileKeyList.forEach(fileKey -> {
|
||||
FindFileKeyResponse response = new FindFileKeyResponse();
|
||||
response.setUrl(fileKey);
|
||||
response.setFileKey(fileKey);
|
||||
resList.add(response);
|
||||
});
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(fileList)) {
|
||||
fileList.forEach(file -> {
|
||||
FindFileKeyResponse response = new FindFileKeyResponse();
|
||||
response.setUrl(file.getFileUrl());
|
||||
response.setFileKey(file.getFileUuid());
|
||||
resList.add(response);
|
||||
});
|
||||
}
|
||||
return resList;
|
||||
}
|
||||
|
||||
private void asyncSaveFile(List<FindFileKeyResponse> resList) {
|
||||
if (CollectionUtil.isEmpty(resList)) {
|
||||
return;
|
||||
}
|
||||
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))
|
||||
)));
|
||||
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).join();
|
||||
}
|
||||
|
||||
private File saveFile(FindFileKeyResponse response) {
|
||||
String url = response.getUrl();
|
||||
String tgtFileKey = url.substring(url.indexOf(HTTP_COM) + 5);
|
||||
String appCode = tgtFileKey.substring(0, tgtFileKey.indexOf("/"));
|
||||
String bizScene = getBizScene(appCode);
|
||||
if (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 String getBizScene(String appCode) {
|
||||
String bizScene = "";
|
||||
switch (appCode) {
|
||||
case "face":
|
||||
bizScene = "face";
|
||||
break;
|
||||
case "idcard":
|
||||
bizScene = "idcard";
|
||||
break;
|
||||
case "bankcard":
|
||||
bizScene = "bankcard";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return bizScene;
|
||||
}
|
||||
|
||||
private List<FindFileKeyResponse> setFileKeyResByUrl(List<String> urlList) {
|
||||
List<FindFileKeyResponse> resList = new ArrayList<>();
|
||||
urlList.stream().forEach(url -> {
|
||||
FindFileKeyResponse response = new FindFileKeyResponse();
|
||||
response.setUrl(file.getFileUrl());
|
||||
response.setFileKey(file.getFileUuid());
|
||||
response.setUrl(url);
|
||||
response.setFileKey(Utility.getUUID());
|
||||
resList.add(response);
|
||||
});
|
||||
return resList;
|
||||
@ -231,6 +464,16 @@ public class FileServiceImpl implements FileService {
|
||||
// 生成上传文件的唯一key
|
||||
String tgtFileKey = Utility.generateFileKey(fileUploadConfig.getDirectory(), uuid, fileConform);
|
||||
|
||||
// 上传文件
|
||||
String fileUrl = fileManager.uploadByStream(
|
||||
fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileName(), dto.getFileContent());
|
||||
|
||||
// 保存失败
|
||||
if (Utility.isBlank(fileUrl)) {
|
||||
log.error("fileUrl is empty");
|
||||
throw new BizException(CodeEnum.FILE_UPLOAD_FAILED);
|
||||
}
|
||||
|
||||
File ossFile = new File();
|
||||
ossFile.setAppChannelBucketNo(fileUploadConfig.getAppChannelBucketNo());
|
||||
ossFile.setAppCode(fileUploadConfig.getAppCode());
|
||||
@ -241,17 +484,6 @@ public class FileServiceImpl implements FileService {
|
||||
ossFile.setStorageUnit(fileUploadConfig.getStorageUnit());
|
||||
ossFile.setStorageSize(fileUploadConfig.getStorageSize());
|
||||
ossFile.setFileFormat(fileConform);
|
||||
// 上传文件
|
||||
String fileUrl = fileManager.uploadByStream(
|
||||
fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileContent());
|
||||
|
||||
// 保存失败
|
||||
if (Utility.isBlank(fileUrl)) {
|
||||
log.error("fileUrl is empty");
|
||||
//fileDao.save(ossFile);
|
||||
throw new BizException(CodeEnum.FILE_UPLOAD_FAILED);
|
||||
}
|
||||
|
||||
ossFile.setFileUuid(uuid);
|
||||
ossFile.setFileUrl(fileUrl);
|
||||
ossFile.setUrlMd5(Utility.getMd5(fileUrl));
|
||||
@ -270,13 +502,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
6
pom.xml
6
pom.xml
@ -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>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user