From fc348855a1724d5e01f997111d9e95ef5c8648eb Mon Sep 17 00:00:00 2001 From: xudawei Date: Fri, 14 Mar 2025 14:40:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:(REQ-3540)=20=E5=8A=A0=E4=B8=8A=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ServerFileController.java | 45 ++++++++++ .../cn/axzo/oss/dal/repository/FileDao.java | 5 ++ .../oss/dal/repository/impl/FileDaoImpl.java | 14 ++++ .../oss/http/api/ServerFileServiceApi.java | 15 +++- .../ServerFileBatchDeleteObjectRequest.java | 42 ++++++++++ .../ServerFileBatchDeleteObjectResponse.java | 42 ++++++++++ .../oss/integration/s3/AliOssService.java | 8 ++ .../integration/s3/HuaWeiCloudService.java | 7 ++ .../s3/impl/AliOssServiceImpl.java | 20 +++++ .../s3/impl/HuaWeiCloudServiceImpl.java | 25 ++++++ .../cn/axzo/oss/manager/api/FileManager.java | 8 ++ .../request/file/DeleteObjectsFileDto.java | 48 +++++++++++ .../response/BatchDeleteObjectsResponse.java | 47 +++++++++++ .../oss/manager/impl/FileManagerImpl.java | 66 +++++++++++++++ .../cn/axzo/oss/service/api/FileService.java | 6 ++ .../oss/service/impl/FileServiceImpl.java | 83 +++++++++++++++++++ 16 files changed, 478 insertions(+), 3 deletions(-) create mode 100644 oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectRequest.java create mode 100644 oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectResponse.java create mode 100644 oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/file/DeleteObjectsFileDto.java create mode 100644 oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/BatchDeleteObjectsResponse.java 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 521376e..6ca999c 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 @@ -29,6 +29,8 @@ import cn.axzo.oss.http.model.ServerFileUploadResponse; import cn.axzo.oss.http.model.ServerFileUploadV2Request; import cn.axzo.oss.http.model.copyobject.ServerFileBatchCopyObjectRequest; import cn.axzo.oss.http.model.copyobject.ServerFileBatchCopyObjectResponse; +import cn.axzo.oss.http.model.copyobject.ServerFileBatchDeleteObjectRequest; +import cn.axzo.oss.http.model.copyobject.ServerFileBatchDeleteObjectResponse; import cn.axzo.oss.http.model.file.FileRenameRequest; import cn.axzo.oss.http.model.file.FileRenameResponse; import cn.axzo.oss.http.model.file.UpdateFileInfoRequest; @@ -43,6 +45,7 @@ import cn.axzo.oss.manager.api.dto.request.ServerFileUploadByUrlDto; import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto; import cn.axzo.oss.manager.api.dto.request.SignUrlDownloadDto; import cn.axzo.oss.manager.api.dto.request.SignUrlUploadDto; +import cn.axzo.oss.manager.api.dto.request.file.DeleteObjectsFileDto; import cn.axzo.oss.manager.api.dto.request.file.UpdateFileInfoDto; import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse; import cn.axzo.oss.service.api.FileByUrlService; @@ -263,4 +266,46 @@ public class ServerFileController implements ServerFileServiceApi { .updateFileInfo(UpdateFileInfoDto.UpdateFileInfo.builder().fileName(request.getNewName()).build()).build(); return CommonResponse.success(FileRenameResponse.builder().updateFlag(this.fileService.updateFileInfo(updateFileInfoDto)).build()); } + + /** + * 删除文件 + */ + public CommonResponse batchDeleteObject(@Valid @RequestBody ServerFileBatchDeleteObjectRequest request) { + AssertUtil.isFalse(Objects.isNull(request) || CollectionUtils.isEmpty(request.getDeleteObjects()), "参数为空"); + //构建删除对象 + DeleteObjectsFileDto deleteObjectsFileDto = this.buildDeleteObjects(request); + //删除逻辑 + this.fileService.deleteObject(deleteObjectsFileDto); + //构建删除对象返回 + return CommonResponse.success(this.buildDeleteResponse(deleteObjectsFileDto)); + } + + /** + * 构建删除对象返回 + */ + private ServerFileBatchDeleteObjectResponse buildDeleteResponse(DeleteObjectsFileDto deleteObjectsFileDto) { + List responses + = deleteObjectsFileDto.getDeleteFiles().stream().map(item -> { + return ServerFileBatchDeleteObjectResponse.ServerFileDeleteObjectResponse.builder() + .fileKey(item.getFileKey()) + .errorCode(item.getErrorCode()).build(); + }).collect(Collectors.toList()); + + return ServerFileBatchDeleteObjectResponse.builder().responses(responses).build(); + } + + /** + * 构建删除对象 + */ + private DeleteObjectsFileDto buildDeleteObjects(ServerFileBatchDeleteObjectRequest request) { + List fileKeys = request.getDeleteObjects().stream().map(ServerFileBatchDeleteObjectRequest.ServerFileDeleteObjectRequest::getFileKey).collect(Collectors.toList()); + + AssertUtil.isFalse(Objects.isNull(request) || CollectionUtils.isEmpty(fileKeys), "参数为空"); + + List deleteObjectFileDtos = fileKeys.stream().map(item -> { + return DeleteObjectsFileDto.DeleteObjectFileDto.builder().fileKey(item).build(); + }).collect(Collectors.toList()); + AssertUtil.isFalse(CollectionUtils.isEmpty(deleteObjectFileDtos), "参数为空"); + return DeleteObjectsFileDto.builder().deleteFiles(deleteObjectFileDtos).build(); + } } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java index a66d9f6..255055d 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java @@ -38,4 +38,9 @@ public interface FileDao extends IService { * 目前只有文件名称更新,后续有其他属性可以添加 */ boolean updateFileById(File file); + + /** + * 根据fileKeys删除 + */ + boolean deleteByFileKeys(List fileKeys); } diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java index 1db07d7..f139101 100644 --- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java +++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java @@ -91,4 +91,18 @@ public class FileDaoImpl extends ServiceImpl implements FileDa .set(StringUtils.isNotBlank(file.getFileName()), File::getFileName, file.getFileName()) .update(); } + + /** + * 根据fileKeys删除 + */ + @Override + public boolean deleteByFileKeys(List fileKeys) { + if (CollectionUtil.isEmpty(fileKeys)) { + return false; + } + return lambdaUpdate().in(File::getFileUuid, fileKeys) + .eq(File::getStatus, FileStatus.SUCCESS) + .eq(File::getIsDelete, TableDelete.UN_DELETED) + .set(File::getIsDelete, TableDelete.DELETED).update(); + } } 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 02574f0..b6669fe 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 @@ -24,6 +24,8 @@ import cn.axzo.oss.http.model.ServerFileUploadResponse; import cn.axzo.oss.http.model.ServerFileUploadV2Request; import cn.axzo.oss.http.model.copyobject.ServerFileBatchCopyObjectRequest; import cn.axzo.oss.http.model.copyobject.ServerFileBatchCopyObjectResponse; +import cn.axzo.oss.http.model.copyobject.ServerFileBatchDeleteObjectRequest; +import cn.axzo.oss.http.model.copyobject.ServerFileBatchDeleteObjectResponse; import cn.axzo.oss.http.model.file.UpdateFileInfoRequest; import cn.axzo.oss.http.model.file.UpdateFileInfoResponse; import cn.azxo.framework.common.model.CommonResponse; @@ -65,10 +67,10 @@ public interface ServerFileServiceApi { CommonResponse uploadV2(ServerFileUploadV2Request request); /** - * 删除文件 - * @param request - * @return + * 删除文件-方法已废弃 + * 建议换成ServerFileServiceApi#deleteObject() */ + @Deprecated @RequestMapping(value = "/api/v1/server/delete", method = RequestMethod.POST) CommonResponse delete(ServerFileDeleteRequest request); @@ -151,4 +153,11 @@ public interface ServerFileServiceApi { @RequestMapping(value = "/api/server/batchCopyObject", method = RequestMethod.POST) CommonResponse updateFileInfo(@Valid @RequestBody UpdateFileInfoRequest request); + /** + * 删除文件 + */ + @RequestMapping(value = "/api/server/deleteObject", method = RequestMethod.POST) + CommonResponse batchDeleteObject(@Valid @RequestBody ServerFileBatchDeleteObjectRequest request); + + } diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectRequest.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectRequest.java new file mode 100644 index 0000000..e191b42 --- /dev/null +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectRequest.java @@ -0,0 +1,42 @@ +package cn.axzo.oss.http.model.copyobject; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.Set; + +/** + * 批量删除对象 + * + * @author xudawei + * @date 2025-03-07 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ServerFileBatchDeleteObjectRequest { + + @NotBlank(message = "appCode must not be null") + private String appCode; + + @NotEmpty(message = "集合对象不能为空") + private Set deleteObjects; + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class ServerFileDeleteObjectRequest { + /** + * 文件标识 + */ + @NotBlank(message = "fileKey不能为空") + private String fileKey; + + } +} diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectResponse.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectResponse.java new file mode 100644 index 0000000..b435aee --- /dev/null +++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/copyobject/ServerFileBatchDeleteObjectResponse.java @@ -0,0 +1,42 @@ +package cn.axzo.oss.http.model.copyobject; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 删除文件返回 + * + * @author xudawei + * @date 2025-03-14 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ServerFileBatchDeleteObjectResponse { + + private List responses; + + @Data + @AllArgsConstructor + @NoArgsConstructor + @Builder + public static class ServerFileDeleteObjectResponse { + /** + * 文件标识 + */ + private String fileKey; + + /** + * 删除标识 + * true:删除成功;false:删除失败 + */ + private String errorCode; + + } + +} diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java index ad323db..2bf10b7 100644 --- a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java @@ -2,8 +2,11 @@ package cn.axzo.oss.integration.s3; import cn.axzo.oss.integration.s3.base.BaseS3Service; import com.aliyun.oss.model.CopyObjectResult; +import com.aliyun.oss.model.DeleteObjectsResult; import com.aliyun.oss.model.SimplifiedObjectMeta; +import java.util.List; + /** * @program: oss * @description: 阿里云oss服务 @@ -46,4 +49,9 @@ public interface AliOssService extends BaseS3Service { * 复制对象 */ CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey); + + /** + * 批量删除File + */ + DeleteObjectsResult batchDeleteFile(String bucketName, List keys); } diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/HuaWeiCloudService.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/HuaWeiCloudService.java index 8f9ea90..f4b27f5 100644 --- a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/HuaWeiCloudService.java +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/HuaWeiCloudService.java @@ -1,10 +1,12 @@ package cn.axzo.oss.integration.s3; import com.obs.services.model.CopyObjectResult; +import com.obs.services.model.DeleteObjectsResult; import com.obs.services.model.ObjectMetadata; import com.obs.services.model.TemporarySignatureResponse; import java.io.InputStream; +import java.util.List; /** * 华为云obs @@ -57,4 +59,9 @@ public interface HuaWeiCloudService { * 复制对象 */ CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey); + + /** + * 删除File + */ + DeleteObjectsResult batchDeleteFile(String bucketName, List keyAndVersions); } diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java index 16093e2..3a957b3 100644 --- a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java @@ -13,6 +13,8 @@ import com.aliyun.oss.OSS; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.CompleteMultipartUploadRequest; import com.aliyun.oss.model.CopyObjectResult; +import com.aliyun.oss.model.DeleteObjectsRequest; +import com.aliyun.oss.model.DeleteObjectsResult; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.InitiateMultipartUploadRequest; @@ -433,4 +435,22 @@ public class AliOssServiceImpl implements AliOssService { return null; } } + + /** + * 批量删除File + */ + @Override + public DeleteObjectsResult batchDeleteFile(String bucketName, List keys) { + try { + log.info("aliyun batchDeleteFile params, bucketName:{}, keys:{}", bucketName, JSON.toJSONString(keys)); + DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName); + deleteObjectsRequest.setKeys(keys); + DeleteObjectsResult deleteObjectsResult = aliOssClient.getClient().deleteObjects(deleteObjectsRequest); + log.info("aliyun batchDeleteFile result, bucketName:{}, keys:{}, deleteObjectsResult:{}", bucketName, JSON.toJSONString(keys),JSON.toJSONString(deleteObjectsResult)); + return deleteObjectsResult; + } catch (Exception e) { + log.warn("aliyun batchDeleteFile exception, bucketName:{}, keys:{}", bucketName, JSON.toJSONString(keys), e); + throw new BizException(CodeEnum.DELETE_FILE_FAIL); + } + } } diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/HuaWeiCloudServiceImpl.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/HuaWeiCloudServiceImpl.java index dce2bae..99e7d12 100644 --- a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/HuaWeiCloudServiceImpl.java +++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/HuaWeiCloudServiceImpl.java @@ -18,12 +18,15 @@ import com.obs.services.model.CompleteMultipartUploadRequest; import com.obs.services.model.CompleteMultipartUploadResult; import com.obs.services.model.CopyObjectResult; import com.obs.services.model.DeleteObjectResult; +import com.obs.services.model.DeleteObjectsRequest; +import com.obs.services.model.DeleteObjectsResult; import com.obs.services.model.DownloadFileRequest; import com.obs.services.model.DownloadFileResult; import com.obs.services.model.GetObjectRequest; import com.obs.services.model.HttpMethodEnum; import com.obs.services.model.InitiateMultipartUploadRequest; import com.obs.services.model.InitiateMultipartUploadResult; +import com.obs.services.model.KeyAndVersion; import com.obs.services.model.ObjectMetadata; import com.obs.services.model.ObsObject; import com.obs.services.model.PartEtag; @@ -422,6 +425,28 @@ public class HuaWeiCloudServiceImpl implements HuaWeiCloudService { } } + /** + * 删除File + */ + @Override + public DeleteObjectsResult batchDeleteFile(String bucketName, List keys) { + try { + if (CollectionUtils.isEmpty(keys)) { + return new DeleteObjectsResult(); + } + log.info("huawei cloud batchDeleteFile params, bucketName:{}, keyAndVersions:{}", bucketName, JSON.toJSONString(keys)); + DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName); + deleteObjectsRequest.setKeyAndVersions(keys.toArray(new KeyAndVersion[keys.size()])); + + DeleteObjectsResult result = huaWeiCloudObsClient.getClient().deleteObjects(deleteObjectsRequest); + log.info("huawei cloud batchDeleteFile result, bucketName:{},deleteObjectResult:{}", bucketName, JsonUtil.obj2Str(result)); + return result; + } catch (Exception e) { + log.warn("huawei cloud batchDeleteFile exception, bucketName:{}", bucketName, e); + throw new BizException(CodeEnum.DELETE_FILE_FAIL); + } + } + public String getUrl(String bucketName, String tgtFileKey) { StringBuilder allBuilder = new StringBuilder(); allBuilder.append("https://"); diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java index a53a04e..22332f9 100644 --- a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java @@ -3,6 +3,7 @@ package cn.axzo.oss.manager.api; import cn.axzo.oss.manager.api.dto.PartETag; import cn.axzo.oss.manager.api.dto.request.CopyObjectCloudDto; import cn.axzo.oss.manager.api.dto.request.MultipartUploadDto; +import cn.axzo.oss.manager.api.dto.request.file.DeleteObjectsFileDto; import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse; import cn.axzo.oss.manager.api.vo.SignUrlUploadVo; @@ -106,4 +107,11 @@ public interface FileManager { * 相同的通道-对象复制 */ Boolean copyObjectWhenSameChannel(CopyObjectCloudDto dto); + + /** + * 批量删除对象 + * 1 华为云删除失败的会返回在errorResults中 + * 2 阿里云删除成功的会返回在errorResults中 + */ + DeleteObjectsFileDto batchDeleteObjects(DeleteObjectsFileDto dto, String bucketName, String channelCode); } diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/file/DeleteObjectsFileDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/file/DeleteObjectsFileDto.java new file mode 100644 index 0000000..d87768b --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/file/DeleteObjectsFileDto.java @@ -0,0 +1,48 @@ +package cn.axzo.oss.manager.api.dto.request.file; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author xudawei@axzo.cn + * @date 2025/3/12 + * @description 删除文件信息 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DeleteObjectsFileDto { + + /** + * 文件集合 + */ + private List deleteFiles; + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class DeleteObjectFileDto { + + /** + * fileKey + */ + private String fileKey; + /** + * 桶key + */ + private String bucketKey; + + /** + * 错误编码 + */ + private String errorCode; + } + + +} diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/BatchDeleteObjectsResponse.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/BatchDeleteObjectsResponse.java new file mode 100644 index 0000000..04f688e --- /dev/null +++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/BatchDeleteObjectsResponse.java @@ -0,0 +1,47 @@ +package cn.axzo.oss.manager.api.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @Author: xudawei + * @Date: 2024/03/12 + * @Description: 授权给第三方下载 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BatchDeleteObjectsResponse { + + + private List deleteObjects; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DeleteObjectResponse { + /** + * 文件 Key + */ + private String fileKey; + + /** + * 桶名称 + */ + private String bucketName; + + /** + * 桶key + */ + private String bucketKey; + } + + + +} diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java index 692e647..d09bd6f 100644 --- a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java +++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java @@ -14,11 +14,13 @@ import cn.axzo.oss.manager.api.FileManager; import cn.axzo.oss.manager.api.dto.PartETag; import cn.axzo.oss.manager.api.dto.request.CopyObjectCloudDto; import cn.axzo.oss.manager.api.dto.request.MultipartUploadDto; +import cn.axzo.oss.manager.api.dto.request.file.DeleteObjectsFileDto; import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse; import cn.axzo.oss.manager.api.vo.SignUrlUploadVo; import com.aliyun.oss.model.SimplifiedObjectMeta; import com.obs.services.model.CopyObjectResult; +import com.obs.services.model.DeleteObjectsResult; import com.obs.services.model.ObjectMetadata; import com.obs.services.model.TemporarySignatureResponse; import lombok.extern.slf4j.Slf4j; @@ -33,7 +35,10 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @Author admin @@ -379,5 +384,66 @@ public class FileManagerImpl implements FileManager { return false; } + /** + * 批量删除对象 + * 1 华为云删除失败的会返回在errorResults中 + * 2 阿里云删除成功的会返回在errorResults中 + */ + public DeleteObjectsFileDto batchDeleteObjects(DeleteObjectsFileDto dto, String bucketName, String channelCode) { + if (StringUtils.isBlank(bucketName) + || StringUtils.isBlank(channelCode) + || Objects.isNull(dto) + || CollectionUtils.isEmpty(dto.getDeleteFiles())) { + return DeleteObjectsFileDto.builder().build(); + } + List bucketKeys = dto.getDeleteFiles().stream().map(DeleteObjectsFileDto.DeleteObjectFileDto::getBucketKey).collect(Collectors.toList()); + ChannelTypeEnum typeEnum = ChannelTypeEnum.getChannelTypeByChannelCode(channelCode); + switch (typeEnum) { + case OBS:// 华为云 + this.deleteToHuaweiCloud(dto, bucketName, bucketKeys); + break; + case OSS:// 阿里云 + this.deleteToAliyun(dto, bucketName, bucketKeys); + default: + BizException.error(CodeEnum.CHANNEL_TYPE_NOT_EXIST); + } + return dto; + } + + /** + * 删除阿里云文件 + */ + private void deleteToAliyun(DeleteObjectsFileDto dto, String bucketName, List bucketKeys) { + com.aliyun.oss.model.DeleteObjectsResult aliResult = aliOssService.batchDeleteFile(bucketName, bucketKeys); + Map deleteMap = aliResult.getDeletedObjects().stream().collect(Collectors.toMap(item -> item, Function.identity(), (x, y) -> x)); + + //阿里云删除成功的会返回在errorResults中 + dto.getDeleteFiles().stream().forEach(item -> { + if (StringUtils.isNotBlank(deleteMap.get(item.getBucketKey()))) { + item.setErrorCode(CodeEnum.SUCCESS.getCode().toString()); + } else { + item.setErrorCode(CodeEnum.DELETE_FILE_FAIL.getCode().toString()); + } + }); + } + + /** + * 删除华为云文件 + */ + private void deleteToHuaweiCloud(DeleteObjectsFileDto dto, String bucketName, List bucketKeys) { + DeleteObjectsResult huaweiResult = huaWeiCloudService.batchDeleteFile(bucketName, bucketKeys); + List errorResults = huaweiResult.getErrorResults(); + + Map errorMap = errorResults.stream().collect(Collectors.toMap(item -> item.getObjectKey(), value -> value.getErrorCode(), (x, y) -> x)); + //华为云删除失败的会返回在errorResults中 + dto.getDeleteFiles().stream().forEach(item -> { + if (StringUtils.isNotBlank(errorMap.get(item.getBucketKey()))) { + item.setErrorCode(errorMap.get(item.getBucketKey())); + } else { + item.setErrorCode(CodeEnum.SUCCESS.getCode().toString()); + } + }); + } + } diff --git a/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java index d16738a..0523cdb 100644 --- a/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java +++ b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java @@ -17,6 +17,7 @@ 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.request.SignUrlDownloadDto; import cn.axzo.oss.manager.api.dto.request.SignUrlUploadDto; +import cn.axzo.oss.manager.api.dto.request.file.DeleteObjectsFileDto; import cn.axzo.oss.manager.api.dto.request.file.UpdateFileInfoDto; import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse; import cn.axzo.oss.manager.api.dto.response.FileInformationResponse; @@ -132,4 +133,9 @@ public interface FileService { * 更新文件信息 */ boolean updateFileInfo(UpdateFileInfoDto updateFileInfoDto); + + /** + * 删除文件信息 + */ + void deleteObject(DeleteObjectsFileDto dto); } 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 5b88c29..607ba84 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 @@ -47,6 +47,7 @@ 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.request.SignUrlDownloadDto; import cn.axzo.oss.manager.api.dto.request.SignUrlUploadDto; +import cn.axzo.oss.manager.api.dto.request.file.DeleteObjectsFileDto; import cn.axzo.oss.manager.api.dto.request.file.UpdateFileInfoDto; import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse; import cn.axzo.oss.manager.api.dto.response.FileInformationResponse; @@ -1401,4 +1402,86 @@ public class FileServiceImpl implements FileService { } return null; } + + /** + * 删除文件信息 + */ + @Override + public void deleteObject(DeleteObjectsFileDto dto) { + if (Objects.isNull(dto) || CollectionUtils.isEmpty(dto.getDeleteFiles())) { + return; + } + // 构建fileKey与bucketKey对象集合 + Pair, File> deletePair = this.buildFileKeyAndBucketKeyList(dto); + + if (Objects.isNull(deletePair)) { + return; + } + // 删除云文件和file表 + DeleteObjectsFileDto deleteObjectsFileDto = this.deleteYunAndFile(deletePair); + + // 重新填充dto中的errorcode + this.rechangeDeleteObjectsFileDto(deleteObjectsFileDto, dto); + } + + /** + * 删除云文件和file表 + */ + private DeleteObjectsFileDto deleteYunAndFile(Pair, File> deletePair) { + // 删除云文件 + DeleteObjectsFileDto deleteObjectsFileDto = this.fileManager.batchDeleteObjects(DeleteObjectsFileDto.builder() + .deleteFiles(deletePair.getKey()).build() + , deletePair.getValue().getBucketName() + , deletePair.getValue().getChannelCode()); + // 删除file文件 + this.deleteFiles(deleteObjectsFileDto); + return deleteObjectsFileDto; + } + + /** + * 重新填充dto中的errorcode + */ + private void rechangeDeleteObjectsFileDto(DeleteObjectsFileDto deleteObjectsFileDto, DeleteObjectsFileDto dto) { + Map fileKeyMap = deleteObjectsFileDto.getDeleteFiles().stream() + .filter(item -> Objects.nonNull(item)) + .collect(Collectors.toMap(key -> key.getFileKey(), Function.identity())); + + dto.getDeleteFiles().stream().forEach(item -> { + if (Objects.nonNull(fileKeyMap.get(item.getFileKey()))) { + item.setErrorCode(fileKeyMap.get(item.getFileKey()).getErrorCode()); + } + }); + } + + /** + * 删除file文件 + */ + private void deleteFiles(DeleteObjectsFileDto deleteObjectsFileDto) { + List delSuccessFileKeys = deleteObjectsFileDto.getDeleteFiles().stream() + .filter(item -> Objects.nonNull(item) && item.getErrorCode().equals(CodeEnum.SUCCESS.getCode().toString())) + .map(DeleteObjectsFileDto.DeleteObjectFileDto::getFileKey).collect(Collectors.toList()); + + this.fileDao.deleteByFileKeys(delSuccessFileKeys); + } + + /** + * 构建fileKey与bucketKey对象集合 + * 1 根据fileKey,查询file表,最终构建fileKey与bucketKey对象集合 + * 2 阿里云与华为云删除最终需要bucketKey,故需要构建bucketKey + */ + private Pair, File> buildFileKeyAndBucketKeyList(DeleteObjectsFileDto dto) { + List fileKeys = dto.getDeleteFiles().stream().map(item -> item.getFileKey()).collect(Collectors.toList()); + List byFileUuids = this.fileDao.getByFileUuids(fileKeys); + if (CollectionUtil.isEmpty(byFileUuids)) { + return null; + } + List deleteObjectFileDtos = byFileUuids.stream().map(item -> { + return DeleteObjectsFileDto.DeleteObjectFileDto.builder() + .fileKey(item.getFileUuid()) + .bucketKey(Utility.generateFileKey(item.getDirectory(), item.getFileUuid(), item.getFileFormat())) + .build(); + }).collect(Collectors.toList()); + File file = byFileUuids.get(0); + return Pair.of(deleteObjectFileDtos, file); + } }