最近更新时间:2025-03-06 10:34:56
1. 该方式支持复制5GB及以下的文件,如需复制5GB以上的文件,请使用分块复制方式。
3. 鉴于性能考虑,推荐您在复制1G以上的文件时采用分块复制方式。
4. 仅支持桶内复制或同Region跨桶复制,不支持跨Region复制。
public void copyObject() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建copy请求,将sourceBucket这个存储空间下的sourceKey这个object复制到destinationBucket这个存储空间下,并命名为destinationObject
CopyObjectRequest request = new CopyObjectRequest("destinationBucket", "destinationObject", "sourceBucket", "sourceKey");
// 设置新文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 或者指定用户的权限
AccessControlList acl = new AccessControlList();
acl.addGrant(new GranteeId("<user-id>"), Permission.Read);
acl.addGrant(new GranteeEmail("<user-email>"), Permission.Write);
request.setAccessControlList(acl);
// 设置新文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置新文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("key1", "value1");
// 设置新文件的元数据指令,REPLACE 表示替换,COPY 表示保留原有元数据
objectMetadata.setHeader(HttpHeaders.XKssMetadataDirective.toString(), "REPLACE");
// 设置新文件的标签指令,REPLACE 表示替换,COPY 表示保留原有标签
objectMetadata.setHeader(HttpHeaders.XKssTaggingDirective.toString(), "REPLACE");
request.setNewObjectMetadata(objectMetadata);
// 设置新文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("key1", "value1");
request.setObjectTagging(objectTagging);
// 如果目的文件已存在,是否覆盖,true:不覆盖,false:覆盖
request.setForbidOverwrite(true);
/*
* 可以指定目的文件的加密方式
* 1. 服务端加密
* 2. 用户提供key的方式进行服务端解密,并设置新的文件的服务端加密
*/
// 1. copy 后的文件以服务端加密方式存储
// ObjectMetadata meta = new ObjectMetadata();
// meta.setSseAlgorithm("AES256");
// request.setNewObjectMetadata(meta);
// 2. copy的文件以用户提供key的方式进行服务端解密,并设置新的文件的服务端加密
// 生成一个密钥,这个密钥需要自己保存好,加密解密都需要
// KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
// symKeyGenerator.init(256);
// SecretKey destKey= symKeyGenerator.generateKey();
// SecretKey sourceKey= ??//当初加密时用的key
// 指定被拷贝的数据是用sourceKey进行加密的,拷贝时将用该key先对数据解密
// request.setSourceSSECustomerKey(new SSECustomerKey(sourceKey));
// 指定拷贝生成的新数据的加密方式
// request.setDestinationSSECustomerKey(new SSECustomerKey(destKey));
// 发起copy请求
ks3Client.copyObject(request);
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
1. 该方式支持复制任意大小的文件。
2. 鉴于性能考虑,推荐您在复制1GB以上的文件时采用分块复制方式。
3. 仅支持桶内复制或同Region跨桶复制,不支持跨Region复制。
public void copyObjectByParts() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 初始化分块复制
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest("dsBucketName", "dstObjectKey");
// 设置新文件的元数据,该方式不支持通过指定 x-kss-metadata-directive 请求头来指定元数据的处理方式
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("key1", "value1");
initRequest.setObjectMeta(objectMetadata);
// 设置新文件的 ACL
initRequest.setCannedAcl(CannedAccessControlList.Private);
// 或者指定用户的权限
AccessControlList acl = new AccessControlList();
acl.addGrant(new GranteeId("<user-id>"), Permission.Read);
acl.addGrant(new GranteeEmail("<user-email>"), Permission.Write);
initRequest.setAcl(acl);
// 设置新文件的存储类型
initRequest.setStorageClass(StorageClass.Standard);
// 设置新文件的标签
initRequest.addObjectTag("key1", "value1");
// 加密方式:服务端加密
initRequest.getObjectMeta().setHeader(HttpHeaders.XKssServerSideEncryption.toString(), "AES256");
// 加密方式:用户提供key的方式进行服务端加密
// 生成一个秘钥,这个秘钥需要自己保存好,加密解密都需要
// KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
// symKeyGenerator.init(256);
// SecretKey secretKey = symKeyGenerator.generateKey();
// // 将 key 保存到文件中
// byte[] encoded = secretKey.getEncoded();
// Files.write(Paths.get("secretKey"), encoded);
// SSECustomerKey sseCustomerKey = new SSECustomerKey(secretKey);
// initRequest.setSseCustomerKey(sseCustomerKey);
// 如果目的文件已存在,是否覆盖,true:不覆盖,false:覆盖
initRequest.setForbidOverwrite(true);
// 发起初始化分块复制请求
InitiateMultipartUploadResult initiateMultipartUploadResult = ks3Client.initiateMultipartUpload(initRequest);
// 获取 uploadId
// uploadId 表示分块复制任务的唯一 ID,用于后续操作,如上传文件块、完成分块上传等
String uploadId = initiateMultipartUploadResult.getUploadId();
// 获取源文件大小
HeadObjectResult headObjectResult = ks3Client.headObject("srcBucketName", "srcObjectKey");
long fileSize = headObjectResult.getObjectMetadata().getContentLength();
// 分片大小。
// 除了最后一个块没有大小限制外,其余的块的大小均要求在100K以上。推荐分片大小为 5M 的整数倍,如:100M。
// 如果不符合上述要求,会返回413状态码。
long partSize = 100 * 1024 * 1024; // 100M
// 计算总共需要分多少块
long totalParts = fileSize / partSize;
if (fileSize % partSize != 0) {
totalParts++;
}
List<PartETag> partETags = new ArrayList<>();
// 分块复制文件
for (int i = 0; i < totalParts; i++) {
// 分片号。每一个上传的分片都有一个分片号,取值范围是1~10000.
int partNum = i + 1;
CopyPartRequest copyPartRequest = new CopyPartRequest("srcBucketName", "srcObjectKey", "dstBucketName", "dstObjectKey", partNum, uploadId);
// 设置该块的起始、结束位置
long startIndex = i * partSize;
long endIndex = startIndex + partSize - 1;
if (endIndex >= fileSize) {
endIndex = fileSize - 1;
}
copyPartRequest.setBeginRange(startIndex);
copyPartRequest.setEndRange(endIndex);
// 如果源 object 使用客户提供的 key 加密,则需要提供
// copyPartRequest.setSourceSSECustomerKey(srcKey);
// 如果目标 object 使用客户提供的 key 加密,则需要提供
// copyPartRequest.setDestinationSSECustomerKey(dstKey);
CopyResult copyResult = ks3Client.copyPart(copyPartRequest);
// 每次上传分片之后,保存返回结果中的 PartETag,用于合并分块。
partETags.add(new PartETag(partNum, copyResult.getETag()));
}
// 完成分块上传
// 在执行完成分片上传操作时,需要提供所有有效的 partETags。
// KS3收到提交的partETags后,会逐一验证每个分片的有效性。
// 当所有的数据分片验证通过后,KS3将把这些分片组合成一个完整的文件。
CompleteMultipartUploadResult completeMultipartUploadResult = ks3Client.completeMultipartUpload("dstBucketName", "dstObjectKey", uploadId, partETags);
System.out.println(completeMultipartUploadResult.geteTag());
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
1. 文件复制时,需要用户对源文件有读取权限,对目标桶有写入权限。
2. 如果目标文件已经存在,且设置了禁止覆盖同名文件(默认),复制操作将会抛出400,对应的ErrorCode为invalidKey
。
纯净模式