diff --git a/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java b/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java index 6bb0f24..4364829 100644 --- a/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java +++ b/oss-client/src/main/java/cn/axzo/oss/client/controller/ServerFileController.java @@ -14,6 +14,8 @@ import cn.axzo.oss.http.model.ApiSignUrlUploadRequest; import cn.axzo.oss.http.model.ApiSignUrlUploadResponse; import cn.axzo.oss.http.model.BatchGetObjectMetaRequest; import cn.axzo.oss.http.model.BatchGetObjectMetaResponse; +import cn.axzo.oss.http.model.FetchUploadSignUrlToPublishRequest; +import cn.axzo.oss.http.model.FetchUploadSignUrlToPublishResponse; import cn.axzo.oss.http.model.FileInformationResponse; import cn.axzo.oss.http.model.FindFileKeyRequest; import cn.axzo.oss.http.model.FindFileKeyResponse; @@ -42,8 +44,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; @@ -223,4 +223,15 @@ public class ServerFileController implements ServerFileServiceApi { ContextInfo.LiteSaasContext liteSaasContext = JSONUtil.toBean(contextInfoLiteJsonStr, ContextInfo.LiteSaasContext.class); return CommonResponse.success(BeanConverter.convert(fileByUrlService.uploadByUrl(dto.getAppCode(), dto.getBizScene(), dto.getFileName(), dto.getFileUrl(), dto.getChannelCode(), dto.getStyle(), liteSaasContext), ServerFileUploadResponse.class)); } + + /** + * 临时授权上传-生成临时url-公有桶 + */ + @Override + public CommonResponse fetchUploadSignUrlToPublish(@Valid @RequestBody FetchUploadSignUrlToPublishRequest request) { + SignUrlUploadDto dto = BeanConvertUtil.copyBean(request, SignUrlUploadDto.class); + dto.setAppCode(dto.getAppCode() + "-public"); + dto.setBizScene(dto.getAppCode() + "-public"); + return CommonResponse.success(BeanConverter.convert(fileService.signUrlUpload(dto, ContextInfo.LiteSaasContext.builder().build()), FetchUploadSignUrlToPublishResponse.class)); + } } diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java index 8e4d452..c1a3afa 100644 --- a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java @@ -6,6 +6,8 @@ import cn.axzo.oss.http.model.ApiSignUrlUploadRequest; import cn.axzo.oss.http.model.ApiSignUrlUploadResponse; import cn.axzo.oss.http.model.BatchGetObjectMetaRequest; import cn.axzo.oss.http.model.BatchGetObjectMetaResponse; +import cn.axzo.oss.http.model.FetchUploadSignUrlToPublishRequest; +import cn.axzo.oss.http.model.FetchUploadSignUrlToPublishResponse; import cn.axzo.oss.http.model.FileInformationResponse; import cn.axzo.oss.http.model.FindFileKeyRequest; import cn.axzo.oss.http.model.FindFileKeyResponse; @@ -117,4 +119,10 @@ public interface ServerFileServiceApi { @RequestMapping(value = "/api/v1/server/uploadByUrl", method = RequestMethod.POST) CommonResponse uploadByUrl(ServerFileUploadByUrlRequest request); + /** + * 临时授权上传-生成临时url-公有桶 + */ + @RequestMapping(value = "/api/v1/server/fetchUploadToPublishSignUrl", method = RequestMethod.POST) + CommonResponse fetchUploadSignUrlToPublish(@Valid @RequestBody FetchUploadSignUrlToPublishRequest request); + } diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ApiSignUrlDownloadRequest.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ApiSignUrlDownloadRequest.java index 9225a7a..72afce4 100644 --- a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ApiSignUrlDownloadRequest.java +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ApiSignUrlDownloadRequest.java @@ -47,4 +47,9 @@ public class ApiSignUrlDownloadRequest { */ private Boolean hasFileName = true; + /** + * 过期时间 + */ + private Long expiration; + } diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishRequest.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishRequest.java new file mode 100644 index 0000000..07057e3 --- /dev/null +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishRequest.java @@ -0,0 +1,68 @@ +package cn.axzo.oss.http.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author: xudawei + * @date: 2024-03-12 + * @description: 授权给第三方下载 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FetchUploadSignUrlToPublishRequest { + /** + * appCode + */ + @NotBlank(message = "appCode not blank") + private String appCode; + /** + * bizScene,对应目录 + */ + @NotBlank(message = "bizScene not blank") + private String bizScene; + /** + * serviceName + */ + private String serviceName; + + /** + * 1-阿里云-aliyun + * 2-华为云-huaweicloud + */ + private Integer channelType; + /** + * 桶名称 + */ + private String bucketName; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 类型 + */ + private String contentType = "multipart/form-data"; + + /** + * 过期时间 + */ + private Long expiration; + + /** + * 是否带上文件名称 + */ + private Boolean hasFileName = true; + /** + * 桶key + */ + private String bucketKey; +} diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishResponse.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishResponse.java new file mode 100644 index 0000000..a217017 --- /dev/null +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/FetchUploadSignUrlToPublishResponse.java @@ -0,0 +1,54 @@ +package cn.axzo.oss.http.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author: xudawei + * @Date: 2024/03/12 + * @Description: 授权给第三方下载 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FetchUploadSignUrlToPublishResponse { + + /** + * 文件临时-URL + */ + private String signUrl; + /** + * 文件 Key + */ + private String fileKey; + + /** + * host + */ + private String host; + + /** + * 类型 + */ + private String contentType; + + /** + * 通道 + * 1-阿里云-aliyun + * 2-华为云-huaweicloud + */ + private String channelCode; + + /** + * 下载url + */ + private String downloadSignUrl; + + /** + * 文件名称 + */ + private String fileName; +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/FetchUploadSignUrlToPublishDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/FetchUploadSignUrlToPublishDto.java new file mode 100644 index 0000000..bfdb07c --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/FetchUploadSignUrlToPublishDto.java @@ -0,0 +1,64 @@ +package cn.axzo.oss.manager.api.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: xudawei + * @date: 2024-03-12 + * @description: 授权给第三方下载 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FetchUploadSignUrlToPublishDto { + /** + * appCode + */ + private String appCode; + /** + * bizScene,对应目录 + */ + private String bizScene; + /** + * serviceName + */ + private String serviceName; + + /** + * 1-阿里云-aliyun + * 2-华为云-huaweicloud + */ + private Integer channelType; + /** + * 桶名称 + */ + private String bucketName; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 类型 + */ + private String contentType = "multipart/form-data"; + + /** + * 过期时间 + */ + private Long expiration; + + /** + * 是否带上文件名称 + */ + private Boolean hasFileName = true; + /** + * 桶key + */ + private String bucketKey; +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/SignUrlDownloadDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/SignUrlDownloadDto.java index 20b670d..078fc8e 100644 --- a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/SignUrlDownloadDto.java +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/SignUrlDownloadDto.java @@ -45,4 +45,9 @@ public class SignUrlDownloadDto { */ private Boolean hasFileName = true; + /** + * 过期时间 + */ + private Long expiration; + } diff --git a/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java index 0304ccb..2c1ab07 100644 --- a/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java +++ b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java @@ -850,7 +850,7 @@ public class FileServiceImpl implements FileService { List httpUrlSignResList = this.buildHttpUrlSignResponse(dto); //3 构建fileKey入参对象集合 - List fileKeyResList = this.buildFileKeyResponse(dto.getFileKeys(), dto.getBizScene(), dto.getStyle(), dto.getHasFileName()); + List fileKeyResList = this.buildFileKeyResponse(dto.getFileKeys(), dto.getBizScene(), dto.getStyle(), dto.getHasFileName(), dto.getExpiration()); //4 1/2/3集合累加 httpUrlResList.addAll(fileKeyResList); httpUrlResList.addAll(httpUrlSignResList); @@ -861,7 +861,7 @@ public class FileServiceImpl implements FileService { /** * 构建fileKey(非http的入参)的返回对象 */ - private List buildFileKeyResponse(List fileKeys, String bizScene, String style, boolean hasFileName) { + private List buildFileKeyResponse(List fileKeys, String bizScene, String style, boolean hasFileName, Long expiration) { if (CollectionUtil.isEmpty(fileKeys)) { return Lists.newArrayList(); } @@ -882,15 +882,15 @@ public class FileServiceImpl implements FileService { List fileBusinessSceneList = fileBusinessSceneManager.queryByBucketNoAndScene(fileList.stream().map(File::getAppChannelBucketNo).collect(Collectors.toSet()), bizScene); Map bizSceneExpireMap = fileBusinessSceneList.stream().collect(Collectors.toMap(FileBusinessScene::getAppChannelBucketNo, FileBusinessScene::getDownloadExpiration, (x, y) -> y)); //构建返回集合 - return this.buildFileKeyRespByFile(fileList, bucketTypeMap, bizSceneExpireMap, style, hasFileName); + return this.buildFileKeyRespByFile(fileList, bucketTypeMap, bizSceneExpireMap, style, hasFileName, expiration); } /** * 通过File对象,构建返回集合 */ - private List buildFileKeyRespByFile(List fileList,Map bucketTypeMap, Map bizSceneExpireMap, String style, boolean hasFileName) { + private List buildFileKeyRespByFile(List fileList,Map bucketTypeMap, Map bizSceneExpireMap, String style, boolean hasFileName, Long expiration) { List responseList = fileList.stream().map(item -> { - Long expire = bizSceneExpireMap.get(item.getAppChannelBucketNo()); + Long expire = Objects.nonNull(expiration) ? expiration : bizSceneExpireMap.get(item.getAppChannelBucketNo()); // bucket下的key String tgtFileKey = Utility.generateFileKey(item.getDirectory(), item.getFileUuid(), item.getFileFormat()); String bucketType = StringUtils.isNotBlank(bucketTypeMap.get(item.getAppChannelBucketNo())) ? bucketTypeMap.get(item.getAppChannelBucketNo()) : BucketTypeEnum.PRIVATE_BUCKET.getCode(); @@ -995,7 +995,7 @@ public class FileServiceImpl implements FileService { if (CollectionUtil.isEmpty(map)) { return httpUrlList.stream().map(item -> SignUrlDownloadResponse.builder().fileKey(item).signUrl(item).build()).collect(Collectors.toList()); } - List responseList = this.buildFileKeyResponse(Lists.newArrayList(map.values()), null, dto.getStyle(), dto.getHasFileName()); + List responseList = this.buildFileKeyResponse(Lists.newArrayList(map.values()), null, dto.getStyle(), dto.getHasFileName(), dto.getExpiration()); if (CollectionUtil.isEmpty(responseList)) { return httpUrlList.stream().map(item -> SignUrlDownloadResponse.builder().fileKey(item).signUrl(item).build()).collect(Collectors.toList()); } @@ -1024,12 +1024,13 @@ public class FileServiceImpl implements FileService { * 从链接中提取fileKey,比如如下链接,获取fileKey:b4148fbee6954c2fa3139471f18a2dcd * https://xx/identity/b4148fbee6954c2fa3139471f18a2dcd.jpg?AccessKeyId=xx&Expires=xx&response-content-disposition=xx&Signature=xx */ - private String signUrlToFileKey(String signUrl) { + public static String signUrlToFileKey(String signUrl) { if (StringUtils.isBlank(signUrl)) { return StringUtils.EMPTY; } if (signUrl.contains("/") && signUrl.contains("?")) { - String fileName = signUrl.substring(signUrl.lastIndexOf("/") + 1, signUrl.indexOf("?")); + signUrl = signUrl.split("\\?")[0]; + String fileName = signUrl.substring(signUrl.lastIndexOf("/") + 1); if (fileName.contains(".")) { return fileName.substring(0, fileName.indexOf(".")); } @@ -1127,6 +1128,7 @@ public class FileServiceImpl implements FileService { */ @Override public List signUrlDownloadNoFile(SignUrlDownloadDto dto) { + // 通过appcode获取文件渠道桶信息 AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(dto.getAppCode(), null); @@ -1134,10 +1136,11 @@ public class FileServiceImpl implements FileService { FileBusinessScene scene = fileBusinessSceneManager .getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), dto.getBizScene()); + Long expiration = Objects.nonNull(dto.getExpiration()) ? dto.getExpiration() : scene.getDownloadExpiration(); return dto.getFileKeys().stream().map(item ->{ //构建返回集合 return this.buildSignUrlDownloadResponse(appChannelBucket.getBucketType(), appChannelBucket.getBucketName() - , item, appChannelBucket.getChannelCode(), item, scene.getDownloadExpiration()); + , item, appChannelBucket.getChannelCode(), item, expiration); }).collect(Collectors.toList()); }