临时授权-优先取入参,其次oss默认配置过期时间

This commit is contained in:
xudawei 2024-03-21 18:08:59 +08:00
parent 0f873d6065
commit 7a3e538910
11 changed files with 111 additions and 30 deletions

View File

@ -268,7 +268,7 @@ public class WebFileController {
/**
* 授权给第三方下载-生成临时url
*/
@PostMapping(value = "/signUrl/download")
@PostMapping(value = "/signUrl/fetchDownload")
@CrossOrigin
public CommonResponse<List<SignUrlDownloadResponse>> signUrlDownload(@Valid @RequestBody SignUrlDownloadDto request) {
//获取用户信息
@ -278,7 +278,7 @@ public class WebFileController {
/**
* 授权给第三方上传-生成临时url
*/
@PostMapping(value = "/signUrl/upload")
@PostMapping(value = "/signUrl/fetchUpload")
@CrossOrigin
public CommonResponse<SignUrlUploadResponse> signUrlUpload(@Valid @RequestBody SignUrlUploadDto request) {
ContextInfo.LiteSaasContext liteSaasContext = Objects.nonNull(ContextInfoHolder.get()) ? ContextInfoHolder.get().lite() : null;

View File

@ -144,14 +144,6 @@ public class File extends Model<File> {
@TableField("is_delete")
private Integer isDelete;
/**
* 临时授权失效时间
* 根据业务入参决定如果业务没有入参则读取file_upload_config#expiration,默认300s
*/
@TableField("expiration")
private Long expiration;
@Override
protected Serializable pkVal() {
return this.id;

View File

@ -96,6 +96,18 @@ public class FileBusinessScene extends Model<FileBusinessScene> {
@TableField("is_delete")
private Integer isDelete;
/**
* 上传-临时授权失效时间,默认1800s即30分钟
*/
@TableField("upload_expiration")
private Long uploadExpiration;
/**
* 下载-临时授权失效时间,默认1800s即30分钟
*/
@TableField("download_expiration")
private Long downloadExpiration;
@Override
protected Serializable pkVal() {

View File

@ -108,13 +108,6 @@ public class FileUploadConfig extends Model<FileUploadConfig> {
@TableField("is_delete")
private Integer isDelete;
/**
* 临时授权失效时间,默认300s即5分钟
*/
@TableField("expiration")
private Long expiration;
@Override
protected Serializable pkVal() {
return this.id;

View File

@ -3,6 +3,8 @@ package cn.axzo.oss.dal.repository;
import cn.axzo.oss.dal.entity.FileBusinessScene;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 文件业务场景 服务类
@ -21,4 +23,10 @@ public interface FileBusinessSceneDao extends IService<FileBusinessScene> {
* @return
*/
FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene);
/**
* 根据bucketNo与场景获取批量FileBusinessScene对象
*/
List<FileBusinessScene> queryByBucketNoAndScene(List<String> bucketNoList, String bizScen);
}

View File

@ -5,7 +5,13 @@ import cn.axzo.oss.dal.entity.FileBusinessScene;
import cn.axzo.oss.dal.mapper.FileBusinessSceneMapper;
import cn.axzo.oss.dal.repository.FileBusinessSceneDao;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
/**
* <p>
@ -31,4 +37,17 @@ public class FileBusinessSceneDaoImpl extends
.eq(FileBusinessScene::getBusinessScene,bizScen)
.eq(FileBusinessScene::getIsDelete, IsDeleteEnum.NO.getCode()).one();
}
/**
* 根据bucketNo与场景获取批量FileBusinessScene对象
*/
@Override
public List<FileBusinessScene> queryByBucketNoAndScene(List<String> bucketNoList, String bizScen) {
if (CollectionUtils.isEmpty(bucketNoList) || StringUtils.isBlank(bizScen)) {
return Lists.newArrayList();
}
return lambdaQuery().in(FileBusinessScene::getAppChannelBucketNo, bucketNoList)
.eq(FileBusinessScene::getBusinessScene,bizScen)
.eq(FileBusinessScene::getIsDelete, IsDeleteEnum.NO.getCode()).list();
}
}

View File

@ -25,4 +25,9 @@ public class ApiSignUrlDownloadRequest {
@NotEmpty(message = "fileKeys not empty")
private List<String> fileKeys;
/**
* bizScene,对应目录
*/
private String bizScene;
}

View File

@ -2,6 +2,8 @@ package cn.axzo.oss.manager.api;
import cn.axzo.oss.dal.entity.FileBusinessScene;
import java.util.List;
/**
* @author: zhangran
* @date: 20210803 15:42
@ -17,4 +19,9 @@ public interface FileBusinessSceneManager {
* @return
*/
FileBusinessScene getByBucketNoAndScene(String bucketNo,String bizScene);
/**
* 指定appcode文件业务场景
*/
List<FileBusinessScene> queryByBucketNoAndScene(List<String> bucketNoList, String bizScene);
}

View File

@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@ -26,4 +27,9 @@ public class SignUrlDownloadDto {
@NotEmpty(message = "fileKeys not empty")
private List<String> fileKeys;
/**
* bizScene,对应目录
*/
private String bizScene;
}

View File

@ -9,6 +9,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author: zhangran
* @date: 20210803 16:36
@ -35,4 +37,13 @@ public class FileBusinessSceneManagerImpl implements FileBusinessSceneManager {
BizException.isEmpty(fileBusinessScene, CodeEnum.APP_CHANNEL_NOT_FOUND);
return fileBusinessScene;
}
/**
* 根据bucketNo与场景获取批量FileBusinessScene对象
*/
@Override
public List<FileBusinessScene> queryByBucketNoAndScene(List<String> bucketNoList, String bizScene) {
return fileBusinessSceneDao
.queryByBucketNoAndScene(bucketNoList, bizScene);
}
}

View File

@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@ -41,6 +42,7 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
@ -264,9 +266,6 @@ public class FileServiceImpl implements FileService {
}
private FileUploadConfig getFileUploadConfig(String appCode, String bizScene, Integer channelType) {
// 检查appCode
checkAppCode(appCode);
// 通过appcode获取文件渠道桶信息
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode, channelType);
@ -337,7 +336,6 @@ public class FileServiceImpl implements FileService {
ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_SUCCESS.getCode());
ossFile.setFileName(fileName);
ossFile.setFileMd5(fileMd5);
ossFile.setExpiration(expiration);
fileDao.save(ossFile);
return ossFile;
}
@ -737,12 +735,18 @@ public class FileServiceImpl implements FileService {
public List<SignUrlDownloadResponse> signUrlDownload(SignUrlDownloadDto dto) {
log.info("signUrl download dto = {}", JsonUtil.obj2Str(dto));
List<File> fileList = fileDao.getByFileUuids(dto.getFileKeys());
if (CollectionUtils.isEmpty(fileList)) {
return Lists.newArrayList();
}
List<FileBusinessScene> fileBusinessSceneList = fileBusinessSceneManager.queryByBucketNoAndScene(fileList.stream().map(File::getAppChannelBucketNo).collect(Collectors.toList()), dto.getBizScene());
Map<String, Long> bizSceneExpireMap = fileBusinessSceneList.stream().collect(Collectors.toMap(FileBusinessScene::getAppChannelBucketNo, FileBusinessScene::getDownloadExpiration, (x, y) -> y));
return fileList.stream().map(item -> {
Long expire = bizSceneExpireMap.get(item.getAppChannelBucketNo());
// bucket下的key
String tgtFileKey = Utility.generateFileKey(item.getDirectory(), item.getFileUuid(), item.getFileFormat());
String signUrl = this.fileManager.signUrlDownload(item.getBucketName(), tgtFileKey, SIGN_URL_DOWNLOAD_EXPIRE_SECOND , item.getChannelCode());
String signUrl = this.fileManager.signUrlDownload(item.getBucketName(), tgtFileKey, Objects.nonNull(expire) ? expire : SIGN_URL_DOWNLOAD_EXPIRE_SECOND , item.getChannelCode());
return SignUrlDownloadResponse.builder()
.signUrl(signUrl)
.fileKey(item.getFileUuid())
@ -758,12 +762,36 @@ public class FileServiceImpl implements FileService {
log.info("signUrl upload dto = {}", JsonUtil.obj2Str(dto));
//1 校验
checkAppCode(dto.getAppCode());
//2 获取文件配置(多个配置获取优先级高)
FileUploadConfig fileUploadConfig = this.signUrlBuildUploadConfig(dto);
FileUploadConfig fileUploadConfig = new FileUploadConfig();
FileBusinessScene scene = new FileBusinessScene();
if (Objects.nonNull(dto.getChannelType()) && StringUtils.isNoneBlank(dto.getBucketName()) && StringUtils.isNoneBlank(dto.getBizScene())) {
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCodeChannelCodeBucket(dto.getAppCode(), dto.getChannelType(), dto.getBucketName());
// 通过渠道桶编码获取到具体文件业务场景
scene = fileBusinessSceneManager
.getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), dto.getBizScene());
// 通过渠道码和桶名称获取指定上传配置
fileUploadConfig = fileUploadConfigManager
.getByUploadConfig(scene.getAppChannelBucketNo(), scene.getDirectory());
} else {
// 通过appcode获取文件渠道桶信息
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(dto.getAppCode(), dto.getChannelType());
// 通过渠道桶编码获取到具体文件业务场景
scene = fileBusinessSceneManager
.getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), dto.getBizScene());
// 通过渠道码和桶名称获取获取指定上传配置
fileUploadConfig = fileUploadConfigManager
.getByUploadConfig(scene.getAppChannelBucketNo(), scene.getDirectory());
}
//操作日志记录
operateLog(dto.toString(), dto.getServiceName(), FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
//3 保存File对象
return this.signUrlSaveFile(dto, fileUploadConfig);
return this.signUrlSaveFile(dto, fileUploadConfig, scene);
}
/**
@ -772,7 +800,7 @@ public class FileServiceImpl implements FileService {
* @param fileUploadConfig
* @return
*/
private SignUrlUploadResponse signUrlSaveFile(SignUrlUploadDto dto, FileUploadConfig fileUploadConfig) {
private SignUrlUploadResponse signUrlSaveFile(SignUrlUploadDto dto, FileUploadConfig fileUploadConfig, FileBusinessScene scene) {
String uuid = Utility.getUUID();
int lastIndexOf = dto.getFileName().lastIndexOf(FileClassEnum.DOT.type);
@ -790,7 +818,7 @@ public class FileServiceImpl implements FileService {
// 生成上传文件的唯一key
String tgtFileKey = Utility.generateFileKey(fileUploadConfig.getDirectory(), uuid, fileFormat);
// 失效时间
Long expiration = this.buildExpiration(dto, fileUploadConfig);
Long expiration = this.buildExpiration(dto, scene);
//1 调用阿里云/华为云 获取临时授权signUrl
SignUrlUploadVo signUrlUpload = this.fileManager.signUrlUpload(fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileName(),expiration
, fileUploadConfig.getChannelCode(), StringUtils.isNotBlank(dto.getContentType()) ? dto.getContentType() : "multipart/form-data");
@ -810,11 +838,11 @@ public class FileServiceImpl implements FileService {
* 临时授权失效时间
* 优先从业务入参取值业务入参失效时间为空则从oss配置中取失效时间
*/
private Long buildExpiration(SignUrlUploadDto dto, FileUploadConfig fileUploadConfig) {
private Long buildExpiration(SignUrlUploadDto dto, FileBusinessScene scene) {
if (Objects.nonNull(dto) && Objects.nonNull(dto.getExpiration())) {
return dto.getExpiration();
}
return fileUploadConfig.getExpiration();
return scene.getUploadExpiration();
}
/**