feat:(REQ-3540) 文件复制接口添加

This commit is contained in:
xudawei 2025-03-10 19:55:02 +08:00
parent 69420e7051
commit 10e746abd4
15 changed files with 565 additions and 25 deletions

View File

@ -1,12 +1,9 @@
package cn.axzo.oss.client.controller; package cn.axzo.oss.client.controller;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.core.utils.converter.BeanConverter; import cn.axzo.core.utils.converter.BeanConverter;
import cn.axzo.framework.auth.domain.ContextInfo; import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.oss.common.enums.ChannelTypeEnum;
import cn.axzo.oss.common.enums.CodeEnum;
import cn.axzo.oss.common.exception.BizException;
import cn.axzo.oss.common.utils.BeanConvertUtil; import cn.axzo.oss.common.utils.BeanConvertUtil;
import cn.axzo.oss.common.utils.UrlUtil;
import cn.axzo.oss.http.api.ServerFileServiceApi; import cn.axzo.oss.http.api.ServerFileServiceApi;
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest; import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse; import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse;
@ -30,27 +27,28 @@ import cn.axzo.oss.http.model.ServerFileUploadByUrlRequest;
import cn.axzo.oss.http.model.ServerFileUploadRequest; import cn.axzo.oss.http.model.ServerFileUploadRequest;
import cn.axzo.oss.http.model.ServerFileUploadResponse; import cn.axzo.oss.http.model.ServerFileUploadResponse;
import cn.axzo.oss.http.model.ServerFileUploadV2Request; 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.manager.api.dto.request.FileCopyObjectDto;
import cn.axzo.oss.manager.api.dto.request.FindFileKeyDto; 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.FindFileUrlDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileCopyToDictDto;
import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto; import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileCopyToDictDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto; import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
import cn.axzo.oss.manager.api.dto.request.ServerFileUploadByUrlDto; 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.ServerFileUploadDto;
import cn.axzo.oss.manager.api.dto.request.SignUrlDownloadDto; 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.SignUrlUploadDto;
import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse; import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse;
import cn.axzo.oss.service.api.FileByUrlService; import cn.axzo.oss.service.api.FileByUrlService;
import cn.axzo.oss.service.api.FileCopyToDictService; import cn.axzo.oss.service.api.FileCopyToDictService;
import cn.axzo.oss.service.api.FileService; import cn.axzo.oss.service.api.FileService;
import cn.azxo.framework.common.model.CommonResponse; import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody; 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 org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -231,4 +229,14 @@ public class ServerFileController implements ServerFileServiceApi {
dto.setBizScene(dto.getAppCode() + "-public"); dto.setBizScene(dto.getAppCode() + "-public");
return CommonResponse.success(BeanConverter.convert(fileService.signUrlUpload(dto, ContextInfo.LiteSaasContext.builder().build()), FetchUploadSignUrlToPublishResponse.class)); return CommonResponse.success(BeanConverter.convert(fileService.signUrlUpload(dto, ContextInfo.LiteSaasContext.builder().build()), FetchUploadSignUrlToPublishResponse.class));
} }
/**
* 复制文件
*/
public CommonResponse<ServerFileBatchCopyObjectResponse> batchCopyObject(ServerFileBatchCopyObjectRequest request) {
AssertUtil.isFalse(Objects.isNull(request) || CollectionUtils.isEmpty(request.getCopyObjects()), "入参为空");
List<FileCopyObjectDto> fileCopyObjectDtos = BeanUtil.copyToList(request.getCopyObjects(), FileCopyObjectDto.class);
List<FileCopyObjectResponse> fileCopyObjectResponses = fileService.batchCopyObject(fileCopyObjectDtos, request.getAppCode());
return CommonResponse.success(ServerFileBatchCopyObjectResponse.builder().responses(BeanUtil.copyToList(fileCopyObjectResponses, ServerFileBatchCopyObjectResponse.ServerFileCopyObjectResponse.class)).build());
}
} }

View File

@ -22,6 +22,8 @@ import cn.axzo.oss.http.model.ServerFileUploadByUrlRequest;
import cn.axzo.oss.http.model.ServerFileUploadRequest; import cn.axzo.oss.http.model.ServerFileUploadRequest;
import cn.axzo.oss.http.model.ServerFileUploadResponse; import cn.axzo.oss.http.model.ServerFileUploadResponse;
import cn.axzo.oss.http.model.ServerFileUploadV2Request; 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.azxo.framework.common.model.CommonResponse; import cn.azxo.framework.common.model.CommonResponse;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -135,4 +137,10 @@ public interface ServerFileServiceApi {
@RequestMapping(value = "/api/server/copyToDict", method = RequestMethod.POST) @RequestMapping(value = "/api/server/copyToDict", method = RequestMethod.POST)
CommonResponse<ServerFileCopyToDictResponse> copyToDict(ServerFileCopyToDictRequest request); CommonResponse<ServerFileCopyToDictResponse> copyToDict(ServerFileCopyToDictRequest request);
/**
* 复制文件
*/
@RequestMapping(value = "/api/server/batchCopyObject", method = RequestMethod.POST)
CommonResponse<ServerFileBatchCopyObjectResponse> batchCopyObject(ServerFileBatchCopyObjectRequest request);
} }

View File

@ -0,0 +1,79 @@
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 ServerFileBatchCopyObjectRequest {
@NotBlank(message = "appCode must not be null")
private String appCode;
@NotEmpty(message = "集合对象不能为空")
private Set<ServerFileCopyObjectRequest> copyObjects;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ServerFileCopyObjectRequest {
/**
* 唯一标识
* 没有唯一标识可以与fileKey一致
*/
@NotBlank(message = "唯一性标识不能为空")
private String fileUuid;
/**
* 目标桶
* 如果目标桶为空,则默认取源桶
*/
private String targetBucketName;
/**
* 目标目录
* 如果目标目录为空,则默认在源目录同级
*/
private String targetDict;
/**
* 目标通道
* 如果目标通道为空,则默认源通道
*/
private String targetChannelCode;
/**
* 文件名称
*/
private String targetFileName;
/**
* 桶名称
*/
private String srcBucketName;
/**
* 桶文件目录
*/
private String srcBucketKey;
/**
* 文件对象key
*/
private String srcFileKey;
}
}

View File

@ -0,0 +1,53 @@
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 2024-07-01
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ServerFileBatchCopyObjectResponse {
private List<ServerFileCopyObjectResponse> responses;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class ServerFileCopyObjectResponse {
/**
* 与入参中的id一致
*/
private String id;
/**
* 原文件的fileKey
*/
private String oldFileKey;
/**
* 原文件的url
*/
private String oldFileUrl;
/**
* 新文件的filekey
*/
private String newFileKey;
private String newUrl;
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.oss.integration.s3; package cn.axzo.oss.integration.s3;
import cn.axzo.oss.integration.s3.base.BaseS3Service; import cn.axzo.oss.integration.s3.base.BaseS3Service;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.SimplifiedObjectMeta; import com.aliyun.oss.model.SimplifiedObjectMeta;
/** /**
@ -40,4 +41,9 @@ public interface AliOssService extends BaseS3Service {
* 通过url上传至OBS * 通过url上传至OBS
*/ */
String uploadByUrl(String bucketName, String tgtFileKey, String fileName, String url); String uploadByUrl(String bucketName, String tgtFileKey, String fileName, String url);
/**
* 复制对象
*/
CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey);
} }

View File

@ -1,5 +1,6 @@
package cn.axzo.oss.integration.s3; package cn.axzo.oss.integration.s3;
import com.obs.services.model.CopyObjectResult;
import com.obs.services.model.ObjectMetadata; import com.obs.services.model.ObjectMetadata;
import com.obs.services.model.TemporarySignatureResponse; import com.obs.services.model.TemporarySignatureResponse;
@ -53,7 +54,7 @@ public interface HuaWeiCloudService {
ObjectMetadata getObjectMeta(String bucketName, String key, String url); ObjectMetadata getObjectMeta(String bucketName, String key, String url);
/** /**
* 元数据 * 复制对象
*/ */
boolean copyToDict(String bucketName, String key, String targetBucketName, String targetKey); CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey);
} }

View File

@ -11,6 +11,7 @@ import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS; import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException; import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CompleteMultipartUploadRequest; import com.aliyun.oss.model.CompleteMultipartUploadRequest;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.InitiateMultipartUploadRequest; import com.aliyun.oss.model.InitiateMultipartUploadRequest;
@ -415,4 +416,17 @@ public class AliOssServiceImpl implements AliOssService {
return getUrl(bucketName, tgtFileKey); return getUrl(bucketName, tgtFileKey);
} }
/**
* 复制对象
*/
@Override
public CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey) {
try {
return aliOssClient.getClient().copyObject(bucketName, key, targetBucketName, targetKey);
} catch (Exception e) {
log.warn("aliyun-copyObject-exception, bucketName:{}, key:{}", bucketName, key, e);
return null;
}
}
} }

View File

@ -15,7 +15,7 @@ import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException; import com.obs.services.exception.ObsException;
import com.obs.services.model.CompleteMultipartUploadRequest; import com.obs.services.model.CompleteMultipartUploadRequest;
import com.obs.services.model.CompleteMultipartUploadResult; import com.obs.services.model.CompleteMultipartUploadResult;
import com.obs.services.model.CopyObjectRequest; import com.obs.services.model.CopyObjectResult;
import com.obs.services.model.DeleteObjectResult; import com.obs.services.model.DeleteObjectResult;
import com.obs.services.model.DownloadFileRequest; import com.obs.services.model.DownloadFileRequest;
import com.obs.services.model.DownloadFileResult; import com.obs.services.model.DownloadFileResult;
@ -475,21 +475,15 @@ public class HuaWeiCloudServiceImpl implements HuaWeiCloudService {
} }
/** /**
* 元数据 * 复制对象
*/ */
@Override @Override
public boolean copyToDict(String bucketName, String key, String targetBucketName, String targetKey) { public CopyObjectResult copyObject(String bucketName, String key, String targetBucketName, String targetKey) {
try { try {
CopyObjectRequest request = new CopyObjectRequest(); return huaWeiCloudObsClient.getClient().copyObject(bucketName, key, targetBucketName, targetKey);
request.setSourceBucketName(bucketName);
request.setSourceObjectKey(key);
request.setDestinationBucketName(targetBucketName);
request.setDestinationObjectKey(targetKey);
huaWeiCloudObsClient.getClient().copyObject(request);
return true;
} catch (Exception e) { } catch (Exception e) {
log.warn("huaweicloud-copyToDict-exception, bucketName:{}, key:{}", bucketName, key, e); log.warn("huaweicloud-copyToDict-exception, bucketName:{}, key:{}", bucketName, key, e);
return false; return null;
} }
} }

View File

@ -1,6 +1,7 @@
package cn.axzo.oss.manager.api; package cn.axzo.oss.manager.api;
import cn.axzo.oss.manager.api.dto.PartETag; 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.MultipartUploadDto;
import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse; import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse;
import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse;
@ -95,4 +96,14 @@ public interface FileManager {
* 构建公开Style * 构建公开Style
*/ */
String buildPublicXImageProcess(String url, String style); String buildPublicXImageProcess(String url, String style);
/**
* 复制对象
*/
Boolean copyObjects(CopyObjectCloudDto dto);
/**
* 相同的通道-对象复制
*/
Boolean copyObjectWhenSameChannel(CopyObjectCloudDto dto);
} }

View File

@ -0,0 +1,84 @@
package cn.axzo.oss.manager.api.dto.request;
import cn.axzo.oss.common.utils.Utility;
import cn.axzo.oss.dal.entity.File;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
/**
* @author xudawei@axzo.cn
* @date 2025/3/10
* @description 对象复制Dto
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CopyObjectCloudDto {
/**
* 源桶名称
* 比如:axzo-oss
*/
private String srcBucketName;
/**
* 源桶key(三方的桶上的目录+文件名称)
* 比如 zeus/recruit_collect/93248404217a4576ba2698183c3fc7a1.xlsx
*/
private String srcBucketKey;
/**
* 源通道
*/
private String srcChannelCode;
/**
* 源Url
*/
private String srcUrl;
/**
* 目的桶名称
*/
private String targetBucketName;
/**
* 目的桶key(三方的桶上的目录+文件名称)
*/
private String targetBucketKey;
/**
* 目的key(文件唯一标识)
* 比如:93248404217a4576ba2698183c3fc7a1
*/
private String targetKey;
private String targetChannelCode;
private String fileName;
private File file;
private String fileUuid;
public static CopyObjectCloudDto create(FileCopyObjectDto fileCopyObjectRequest, File file) {
// 入参中有通道则优先取入参否则取源通道
String targetChannelCode = StringUtils.isBlank(fileCopyObjectRequest.getTargetChannelCode()) ? file.getChannelCode() : fileCopyObjectRequest.getTargetChannelCode();
String targetBucketName = StringUtils.isBlank(fileCopyObjectRequest.getTargetBucketName()) ? file.getBucketName() : fileCopyObjectRequest.getTargetBucketName();
String targetBucketDict = StringUtils.isBlank(fileCopyObjectRequest.getTargetDict()) ? file.getDirectory() : fileCopyObjectRequest.getTargetDict();
String fileName = StringUtils.isBlank(fileCopyObjectRequest.getTargetFileName()) ? file.getFileName() : fileCopyObjectRequest.getTargetFileName();
String uuid = Utility.getUUID();
return CopyObjectCloudDto.builder()
.srcBucketName(file.getBucketName())
.srcBucketKey(Utility.generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat()))
.srcChannelCode(file.getChannelCode())
.targetBucketName(targetBucketName)
.targetBucketKey(Utility.generateFileKey(targetBucketDict, uuid, file.getFileFormat()))
.targetKey(uuid)
.targetChannelCode(targetChannelCode)
.fileName(fileName)
.file(file)
.fileUuid(fileCopyObjectRequest.getFileUuid())
.build();
}
}

View File

@ -0,0 +1,63 @@
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 xudawei@axzo.cn
* @date 2025/3/10
* @description 对象复制DTO
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileCopyObjectDto {
/**
* 唯一标识
* 没有唯一标识可以与fileKey一致
*/
private String fileUuid;
/**
* 目标桶
* 如果目标桶为空,则默认取源桶
*/
private String targetBucketName;
/**
* 目标目录
* 如果目标目录为空,则默认在源目录同级
*/
private String targetDict;
/**
* 目标通道
* 如果目标通道为空,则默认源通道
*/
private String targetChannelCode;
/**
* 文件名称
*/
private String targetFileName;
/**
* 桶名称
*/
private String srcBucketName;
/**
* 桶文件目录
*/
private String srcBucketKey;
/**
* 文件对象key
*/
private String srcFileKey;
}

View File

@ -0,0 +1,71 @@
package cn.axzo.oss.manager.api.dto.response;
import cn.axzo.oss.manager.api.dto.request.CopyObjectCloudDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
/**
* @author xudawei@axzo.cn
* @date 2025/3/10
* @description 对象复制DTO
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileCopyObjectResponse {
/**
* 唯一标识没有唯一标识可以与fileKey一致
*/
@NotBlank(message = "唯一性标识不能为空")
private String fileUuid;
/**
* 目标桶
* 如果目标桶为空,则默认取源桶
*/
private String targetFileKey;
/**
* 目标通道
* 如果目标通道为空,则默认源通道
*/
private String targetChannelCode;
/**
* 桶名称
*/
private String bucketName;
/**
* 桶文件目录
*/
private String bucketDict;
/**
* 文件对象key
*/
private String fileKey;
/**
* 文件名称
*/
private String fileName;
public static FileCopyObjectResponse create(CopyObjectCloudDto item) {
return FileCopyObjectResponse.builder()
.fileUuid(item.getFileUuid())
.targetFileKey(item.getTargetKey())
.targetChannelCode(item.getTargetChannelCode())
// .targetDownloadUrl(this.fileManager.fetchDownloadUrl(item.getFile().getb))
.bucketName(item.getFile().getBucketName())
.bucketDict(item.getFile().getDirectory())
.fileKey(item.getFile().getFileUuid())
.fileName(item.getFileName())
.build();
}
}

View File

@ -12,12 +12,13 @@ import cn.axzo.oss.integration.s3.AliOssService;
import cn.axzo.oss.integration.s3.HuaWeiCloudService; import cn.axzo.oss.integration.s3.HuaWeiCloudService;
import cn.axzo.oss.manager.api.FileManager; import cn.axzo.oss.manager.api.FileManager;
import cn.axzo.oss.manager.api.dto.PartETag; 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.MultipartUploadDto;
import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse; import cn.axzo.oss.manager.api.dto.response.ManaGetObjectMetaResponse;
import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse;
import cn.axzo.oss.manager.api.vo.SignUrlUploadVo; import cn.axzo.oss.manager.api.vo.SignUrlUploadVo;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.model.SimplifiedObjectMeta; import com.aliyun.oss.model.SimplifiedObjectMeta;
import com.obs.services.model.CopyObjectResult;
import com.obs.services.model.ObjectMetadata; import com.obs.services.model.ObjectMetadata;
import com.obs.services.model.TemporarySignatureResponse; import com.obs.services.model.TemporarySignatureResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -346,4 +347,37 @@ public class FileManagerImpl implements FileManager {
return url; return url;
} }
/**
* 复制对象
*/
@Override
public Boolean copyObjects(CopyObjectCloudDto dto) {
// 相同的通道-对象复制
if (dto.getSrcChannelCode().equals(dto.getTargetChannelCode())) {
return this.copyObjectWhenSameChannel(dto);
}
// 不同的通道通过url上传至云(通过url复制至云)
String url = this.uploadByUrl(dto.getTargetBucketName(), dto.getTargetKey(), dto.getFileName(), dto.getSrcUrl(), dto.getTargetChannelCode());
return StringUtils.isBlank(url) ? false : true;
}
/**
* 相同的通道-对象复制
*/
public Boolean copyObjectWhenSameChannel(CopyObjectCloudDto dto) {
ChannelTypeEnum typeEnum = ChannelTypeEnum.getChannelTypeByChannelCode(dto.getSrcChannelCode());
switch (typeEnum) {
case OBS:// 华为云
CopyObjectResult huaweiResult = huaWeiCloudService.copyObject(dto.getSrcBucketName(), dto.getSrcBucketKey(), dto.getTargetBucketName(), dto.getTargetKey());
return Objects.isNull(huaweiResult) ? false : true;
case OSS:// 阿里云
com.aliyun.oss.model.CopyObjectResult aliResult = aliOssService.copyObject(dto.getSrcBucketName(), dto.getSrcBucketKey(), dto.getTargetBucketName(), dto.getTargetKey());
return Objects.isNull(aliResult) ? false : true;
default:
BizException.error(CodeEnum.CHANNEL_TYPE_NOT_EXIST);
}
return false;
}
} }

View File

@ -4,6 +4,7 @@ import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.oss.dal.entity.AppChannelBucket; import cn.axzo.oss.dal.entity.AppChannelBucket;
import cn.axzo.oss.dal.entity.FileUploadConfig; import cn.axzo.oss.dal.entity.FileUploadConfig;
import cn.axzo.oss.manager.api.dto.request.DeleteFileDto; import cn.axzo.oss.manager.api.dto.request.DeleteFileDto;
import cn.axzo.oss.manager.api.dto.request.FileCopyObjectDto;
import cn.axzo.oss.manager.api.dto.request.FindFileKeyDto; 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.FindFileUrlDto;
import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto; import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto;
@ -16,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.ServerFileUploadDto;
import cn.axzo.oss.manager.api.dto.request.SignUrlDownloadDto; 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.SignUrlUploadDto;
import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse;
import cn.axzo.oss.manager.api.dto.response.FileInformationResponse; 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.FindFileKeyResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse; import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse;
@ -117,4 +119,11 @@ public interface FileService {
* 授权给第三方下载 * 授权给第三方下载
*/ */
List<SignUrlDownloadResponse> signUrlDownloadNoFile(SignUrlDownloadDto dto); List<SignUrlDownloadResponse> signUrlDownloadNoFile(SignUrlDownloadDto dto);
/**
* 复制文件
* 1 不同通道则通过url进行复制
* 2 相同通道则直接调用复制方法
*/
List<FileCopyObjectResponse> batchCopyObject(List<FileCopyObjectDto> dtoList, String appCode);
} }

View File

@ -1,5 +1,6 @@
package cn.axzo.oss.service.impl; package cn.axzo.oss.service.impl;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.core.utils.converter.BeanConverter; import cn.axzo.core.utils.converter.BeanConverter;
import cn.axzo.framework.auth.domain.ContextInfo; import cn.axzo.framework.auth.domain.ContextInfo;
import cn.axzo.log.platform.client.LogPlatClient; import cn.axzo.log.platform.client.LogPlatClient;
@ -31,7 +32,9 @@ import cn.axzo.oss.manager.api.FileBusinessSceneManager;
import cn.axzo.oss.manager.api.FileManager; import cn.axzo.oss.manager.api.FileManager;
import cn.axzo.oss.manager.api.FileUploadConfigManager; import cn.axzo.oss.manager.api.FileUploadConfigManager;
import cn.axzo.oss.manager.api.dto.PartETag; 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.DeleteFileDto; import cn.axzo.oss.manager.api.dto.request.DeleteFileDto;
import cn.axzo.oss.manager.api.dto.request.FileCopyObjectDto;
import cn.axzo.oss.manager.api.dto.request.FindFileKeyDto; 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.FindFileUrlDto;
import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto; import cn.axzo.oss.manager.api.dto.request.GetObjectMetaDto;
@ -44,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.ServerFileUploadDto;
import cn.axzo.oss.manager.api.dto.request.SignUrlDownloadDto; 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.SignUrlUploadDto;
import cn.axzo.oss.manager.api.dto.response.FileCopyObjectResponse;
import cn.axzo.oss.manager.api.dto.response.FileInformationResponse; 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.FindFileKeyResponse;
import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse; import cn.axzo.oss.manager.api.dto.response.FindFileUrlResponse;
@ -54,11 +58,9 @@ import cn.axzo.oss.manager.api.dto.response.ServerFileDownloadResponse;
import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse; import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlDownloadResponse;
import cn.axzo.oss.manager.api.dto.response.SignUrlUploadResponse; import cn.axzo.oss.manager.api.dto.response.SignUrlUploadResponse;
import cn.axzo.oss.manager.api.vo.SignUrlUploadVo;
import cn.axzo.oss.service.api.FileService; import cn.axzo.oss.service.api.FileService;
import cn.axzo.oss.service.metafile.WithFileFactory; import cn.axzo.oss.service.metafile.WithFileFactory;
import cn.axzo.oss.service.metafile.WithFileService; import cn.axzo.oss.service.metafile.WithFileService;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair; import cn.hutool.core.lang.Pair;
@ -89,6 +91,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME; import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
@ -1258,4 +1261,106 @@ public class FileServiceImpl implements FileService {
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
/**
* 复制文件
* 1 不同通道则通过url进行复制
* 2 相同通道则直接调用复制方法
*/
public List<FileCopyObjectResponse> batchCopyObject(List<FileCopyObjectDto> dtoList, String appCode) {
AssertUtil.isFalse(CollectionUtils.isEmpty(dtoList), "请求入参为空");
//校验appCode
this.checkAppCode(appCode);
//通过fileKeys复制文件
List<CopyObjectCloudDto> cloudDtos = this.batchCopyObjectByFileKeys(dtoList);
//保存文件表
return this.saveFiles(cloudDtos);
}
/**
* 保存文件表
*/
private List<FileCopyObjectResponse> saveFiles(List<CopyObjectCloudDto> cloudDtos) {
List<FileCopyObjectResponse> responses = new ArrayList<>();
List<File> fileList = cloudDtos.stream().map(item -> {
//复制文件-构建file对象
File ossFile = this.buildFileWhenCopyObject(item);
//构建返回对象
responses.add(FileCopyObjectResponse.create(item));
return ossFile;
}).collect(Collectors.toList());
if (CollectionUtil.isEmpty(cloudDtos)) {
return Lists.newArrayList();
}
this.fileDao.saveBatch(fileList);
return responses;
}
/**
* 复制文件-构建file对象
*/
private File buildFileWhenCopyObject(CopyObjectCloudDto item) {
File ossFile = new File();
ossFile.setAppChannelBucketNo(item.getFile().getAppChannelBucketNo());
ossFile.setAppCode(item.getFile().getAppCode());
ossFile.setChannelCode(item.getTargetChannelCode());
ossFile.setBucketName(item.getTargetBucketName());
ossFile.setDirectory(item.getTargetBucketKey());
ossFile.setStorageUnit(item.getFile().getStorageUnit());
ossFile.setStorageSize(item.getFile().getStorageSize());
ossFile.setFileFormat(item.getFile().getFileFormat());
ossFile.setFileUuid(item.getTargetKey());
ossFile.setFileUrl(this.fileManager.fetchDownloadUrl(item.getTargetBucketName(), Utility.generateFileKey(item.getTargetBucketKey(), item.getTargetKey(), item.getFile().getFileFormat()), item.getTargetChannelCode()));
ossFile.setUrlMd5(Utility.getMd5(ossFile.getFileUrl()));
ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_SUCCESS.getCode());
ossFile.setFileName(item.getFileName());
ossFile.setFileMd5(Utility.getMd5(ossFile.getFileUrl()));
return ossFile;
}
/**
* 通过fileKeys复制文件
*/
private List<CopyObjectCloudDto> batchCopyObjectByFileKeys(List<FileCopyObjectDto> dtoList) {
List<String> fileKeys = dtoList.stream()
.filter(item -> StringUtils.isNotBlank(item.getSrcFileKey()))
.map(FileCopyObjectDto::getSrcFileKey).collect(Collectors.toList());
Map<String, FileCopyObjectDto> reqFileKeyMap = dtoList.stream()
.filter(item -> StringUtils.isNotBlank(item.getSrcFileKey()))
.collect(Collectors.toMap(item -> item.getSrcFileKey(), Function.identity()));
//查询file数据表获取源对象
List<File> fileList = fileDao.getByFileUuids(fileKeys);
if (CollectionUtil.isEmpty(fileList)) {
return Lists.newArrayList();
}
//通过文件表完成文件对象复制
return this.doBatchCopyObjectByFiles(reqFileKeyMap, fileList);
}
/**
* 通过文件表-文件对象复制
* 注意此方法是根据业务文件复制
* 底层通用方法fileManager.copyObjects(dto);
*/
private List<CopyObjectCloudDto> doBatchCopyObjectByFiles(Map<String, FileCopyObjectDto> reqFileKeyMap, List<File> fileList) {
List<CopyObjectCloudDto> returnList = Lists.newArrayList();
for (File file : fileList) {
if (Objects.isNull(reqFileKeyMap.get(file.getFileUuid()))) {
continue;
}
FileCopyObjectDto fileCopyObjectRequest = reqFileKeyMap.get(file.getFileUuid());
if (Objects.isNull(fileCopyObjectRequest)) {
continue;
}
CopyObjectCloudDto dto = CopyObjectCloudDto.create(fileCopyObjectRequest, file);
this.fileManager.copyObjects(dto);
returnList.add(dto);
}
return returnList;
}
} }