最近更新时间:2025-09-29 18:48:22
copyFile() 方法支持同Region的存储空间之间复制文件,用户无需关心文件大小,SDK 会自动根据文件大小进行简单复制或分块复制。
1. 支持断点续传,每块复制完成后SDK会记录到断点文件中,如果发生意外使复制中断,再次复制该文件时,会自动恢复上次的复制进度。
2. 支持复制/设置元数据、ACL、存储类型、标签等。
3. 支持进度回调。
4. 支持自动校验 CRC64。
5. 支持 KS3 托管密钥的服务端加密、用户提供密钥的服务端加密。
public void copyFile() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 初始化上传文件请求,设置 bucket,objectKey
CopyFileRequest request = new CopyFileRequest("srcBucket", "srcObjectKey", "dstBucket", "dstObjectKey");
// 设置分块大小
request.setPartSize(5 * 1024 * 1024);
// 设置并发数
request.setTaskNum(10);
// 设置是否禁止覆盖
request.setForbidOverwrite(true);
// 设置 metadata,可选,默认复制源文件的 metadata
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("text/plain");
metadata.setUserMeta("key1", "value1");
request.setObjectMetadata(metadata);
// 设置访问权限,可选,默认与源文件相同
request.setCannedAcl(CannedAccessControlList.Private);
// 或者设置自定义权限
AccessControlList accessControlList = new AccessControlList();
accessControlList.addGrant(new GranteeId("id1"), Permission.Read);
accessControlList.addGrant(new GranteeId("id2"), Permission.Write);
request.setAccessControlList(accessControlList);
// 设置存储类型,可选,默认与源文件相同
request.setStorageClass(StorageClass.Standard);
// 设置标签,可选,默认与源文件相同
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("key1", "value1");
objectTagging.addObjectTag("key2", "value2");
request.setObjectTagging(objectTagging);
// 设置复制源文件的元数据,true:复制源文件的元数据,忽略本次设置的 metadata,false:不复制源文件的元数据,默认为 true
request.setCopySrcMetadata(true);
// 设置复制源文件的标签,true:复制源文件的标签,忽略本次设置的标签,false:不复制源文件的标签,默认为 true
request.setCopySrcTagging(true);
// 设置断点续传开关,默认关闭
request.setEnableCheckpoint(true);
// 设置断点续传文件地址,默认为:<uploadFilePath>.ucp
request.setCheckpointFile("/data/test-file.ucp");
// 如果源文件是客户提供密钥的服务端加密的,则需要设置客户的密钥
// request.setSrcSseCustomerKey(srcCustomerKey);
// 如果目标文件需要使用客户提供密钥的服务端加密,则需要设置客户的密钥
// request.setDstSseCustomerKey(dstCustomerKey);
// 设置进度回调,可选
ProgressListener listener = new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("Event Type: " + progressEvent.getEventType());
System.out.println("Event Bytes: " + progressEvent.getBytes());
}
};
request.setProgressListener(listener);
// 启用 CRC64 校验
ks3Client.getKs3config().setCrcCheckEnabled(true);
// 开始复制文件
CopyFileResult result = ks3Client.copyFile(request);
System.out.println("ETag: " + result.getETag());
System.out.println("Crc64Ecma: " + result.getCrc64Ecma());
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}public void copyDir() {
// 初始化 transferManager,自定义线程数和队列大小
TransferManager transferManager = new TransferManager(ks3Client, 5, 10 * 1024 * 1024);
try {
// 初始化复制文件请求提供器,用于设置复制文件的元数据、存储类型、ACL、标签等
// 复制文件请求提供器是可选的,如果要使用源文件的元数据、存储类型、ACL、标签等,可以不设置
CopyFileRequestProvider copyFileRequestProvider = new CopyFileRequestProvider() {
@Override
public void provide(CopyFileRequest request) {
// 设置复制文件的分块大小
request.setPartSize(50 * 1024 * 1024);
// 设置复制文件的线程数
request.setTaskNum(5);
// 设置复制文件的元数据,如果没有设置或 MetadataDirective 没有设置为 REPLACE,使用源文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("my-meta-key", "my-meta-value");
// 如果没有设置 MetadataDirective,默认是 COPY,即使用源文件的元数据,如果设置为 REPLACE,则使用自定义的元数据
// objectMetadata.setMetadataDirective("REPLACE");
// 如果没有设置 TaggingDirective,默认是 COPY,即使用源文件的标签,如果设置为 REPLACE,则使用自定义的标签
// objectMetadata.setTaggingDirective("REPLACE");
request.setObjectMetadata(objectMetadata);
// 设置复制文件的存储类型,如果没有设置或 StorageClass 没有设置,使用源文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置复制文件的ACL,如果没有设置 CannedAcl 且没有设置 ACL,使用源文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 设置复制文件的自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("my-grantee-id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置复制文件的标签,如果没有设置或 TaggingDirective 没有设置为 REPLACE,使用源文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("my-tag-key", "my-tag-value");
request.setObjectTagging(objectTagging);
// 设置进度监听器
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("ProgressEvent: " + progressEvent);
}
});
// 设置其他...
}
};
// 复制文件夹
TransferResult transferResult = transferManager.copyDir("my-bucket", "my-src-prefix/",
"my-bucket", "my-dst-prefix/", copyFileRequestProvider);
for (TaskResult successFile : transferResult.getSuccessFiles()) {
System.out.println("Copy file success, key: " + successFile.getObjectKey() +
", eTag: " + successFile.getETag() + ", crc64Ecma: " + successFile.getCrc64Ecma());
}
for (ErrorFile errorFile : transferResult.getErrorFiles()) {
System.out.println("Copy file failed, key: " + errorFile.getObjectKey() + ", error message: " + errorFile.getErrorMessage());
}
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
transferManager.shutdown();
}
}public void copyFileList() {
// 初始化 transferManager,自定义线程数和队列大小
TransferManager transferManager = new TransferManager(ks3Client, 5, 10 * 1024 * 1024);
try {
// 初始化复制文件请求提供器,用于设置复制文件的元数据、存储类型、ACL、标签等
// 复制文件请求提供器是可选的,如果要使用源文件的元数据、存储类型、ACL、标签等,可以不设置
CopyFileRequestProvider copyFileRequestProvider = new CopyFileRequestProvider() {
@Override
public void provide(CopyFileRequest request) {
// 设置复制文件的分块大小
request.setPartSize(50 * 1024 * 1024);
// 设置复制文件的线程数
request.setTaskNum(5);
// 设置复制文件的元数据,如果没有设置或 MetadataDirective 没有设置为 REPLACE,使用源文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("my-meta-key", "my-meta-value");
// 如果没有设置 MetadataDirective,默认是 COPY,即使用源文件的元数据,如果设置为 REPLACE,则使用自定义的元数据
// objectMetadata.setMetadataDirective("REPLACE");
// 如果没有设置 TaggingDirective,默认是 COPY,即使用源文件的标签,如果设置为 REPLACE,则使用自定义的标签
// objectMetadata.setTaggingDirective("REPLACE");
request.setObjectMetadata(objectMetadata);
// 设置复制文件的存储类型,如果没有设置或 StorageClass 没有设置,使用源文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置复制文件的ACL,如果没有设置 CannedAcl 且没有设置 ACL,使用源文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 设置复制文件的自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("my-grantee-id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置复制文件的标签,如果没有设置或 TaggingDirective 没有设置为 REPLACE,使用源文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("my-tag-key", "my-tag-value");
request.setObjectTagging(objectTagging);
// 设置进度监听器
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("ProgressEvent: " + progressEvent);
}
});
// 设置其他...
}
};
// 源文件的 key 列表
List<String> srcKeyList = Arrays.asList("my-src-prefix/file1.txt", "my-src-prefix/file2.txt", "my-src-prefix/file3.txt");
// 目标文件的 key 列表
List<String> dstKeyList = Arrays.asList("my-dst-prefix/file1.txt", "my-dst-prefix/file2.txt", "my-dst-prefix/file3.txt");
// 复制文件夹
TransferResult transferResult = transferManager.copyFileList("my-bucket", srcKeyList,
"my-bucket", dstKeyList, copyFileRequestProvider);
for (TaskResult successFile : transferResult.getSuccessFiles()) {
System.out.println("Copy file success, key: " + successFile.getObjectKey() +
", eTag: " + successFile.getETag() + ", crc64Ecma: " + successFile.getCrc64Ecma());
}
for (ErrorFile errorFile : transferResult.getErrorFiles()) {
System.out.println("Copy file failed, key: " + errorFile.getObjectKey() + ", error message: " + errorFile.getErrorMessage());
}
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
transferManager.shutdown();
}
}跨区域复制文件,本质上是将源文件进行下载,并上传到目标桶,即使用用户的本地网络进行文件的读写,复制速度与用户的网络带宽及 CPU 等资源相关。如果使用外网 endpoint 进行下载,会产生下行流量费用,具体请参考”计费方式和计量项说明“文档。
public void copyFileAcrossRegion() {
// 初始化 transferManager,自定义线程数和队列大小
TransferManager transferManager = new TransferManager(ks3Client, 5, 10 * 1024 * 1024);
try {
// 初始化上传文件请求提供器,用于设置复制文件的元数据、存储类型、ACL、标签等
// 上传文件请求提供器是可选的,如果要使用源文件的元数据、存储类型、ACL、标签等,可以不设置
UploadFileRequestProvider uploadFileRequestProvider = new UploadFileRequestProvider() {
@Override
public void provide(UploadFileRequest request) {
// 设置复制文件的分块大小
request.setPartSize(50 * 1024 * 1024);
// 设置复制文件的线程数
request.setTaskNum(5);
// 设置复制文件的元数据,如果没有设置或 MetadataDirective 没有设置为 REPLACE,使用源文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("my-meta-key", "my-meta-value");
// 如果没有设置 MetadataDirective,默认是 COPY,即使用源文件的元数据,如果设置为 REPLACE,则使用自定义的元数据
// objectMetadata.setMetadataDirective("REPLACE");
// 如果没有设置 TaggingDirective,默认是 COPY,即使用源文件的标签,如果设置为 REPLACE,则使用自定义的标签
// objectMetadata.setTaggingDirective("REPLACE");
request.setObjectMetadata(objectMetadata);
// 设置复制文件的存储类型,如果没有设置或 StorageClass 没有设置,使用源文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置复制文件的ACL,如果没有设置 CannedAcl 且没有设置 ACL,使用源文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 设置复制文件的自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("my-grantee-id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置复制文件的标签,如果没有设置或 TaggingDirective 没有设置为 REPLACE,使用源文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("my-tag-key", "my-tag-value");
request.setObjectTagging(objectTagging);
// 设置进度监听器
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("ProgressEvent: " + progressEvent);
}
});
// 设置其他...
}
};
// 初始化目标 Ks3Client,参见“初始化”文档
Ks3Client dstKs3Client = initKs3Client();
// 复制文件
UploadFileResult uploadFileResult = transferManager.copyFileAcrossRegion("my-bucket", "my-src-prefix/file1.txt",
"my-bucket-other-region", "my-dst-prefix/file1.txt", dstKs3Client, uploadFileRequestProvider);
System.out.println("Copy file success, key: " + uploadFileResult.getObjectKey() +
", eTag: " + uploadFileResult.getETag() + ", crc64Ecma: " + uploadFileResult.getCrc64Ecma());
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
transferManager.shutdown();
}
}public void copyDirAcrossRegion() {
// 初始化 transferManager,自定义线程数和队列大小
TransferManager transferManager = new TransferManager(ks3Client, 5, 10 * 1024 * 1024);
try {
// 初始化上传文件请求提供器,用于设置复制文件的元数据、存储类型、ACL、标签等
// 上传文件请求提供器是可选的,如果要使用源文件的元数据、存储类型、ACL、标签等,可以不设置
UploadFileRequestProvider uploadFileRequestProvider = new UploadFileRequestProvider() {
@Override
public void provide(UploadFileRequest request) {
// 设置复制文件的分块大小
request.setPartSize(50 * 1024 * 1024);
// 设置复制文件的线程数
request.setTaskNum(5);
// 设置复制文件的元数据,如果没有设置或 MetadataDirective 没有设置为 REPLACE,使用源文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("my-meta-key", "my-meta-value");
// 如果没有设置 MetadataDirective,默认是 COPY,即使用源文件的元数据,如果设置为 REPLACE,则使用自定义的元数据
// objectMetadata.setMetadataDirective("REPLACE");
// 如果没有设置 TaggingDirective,默认是 COPY,即使用源文件的标签,如果设置为 REPLACE,则使用自定义的标签
// objectMetadata.setTaggingDirective("REPLACE");
request.setObjectMetadata(objectMetadata);
// 设置复制文件的存储类型,如果没有设置或 StorageClass 没有设置,使用源文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置复制文件的ACL,如果没有设置 CannedAcl 且没有设置 ACL,使用源文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 设置复制文件的自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("my-grantee-id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置复制文件的标签,如果没有设置或 TaggingDirective 没有设置为 REPLACE,使用源文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("my-tag-key", "my-tag-value");
request.setObjectTagging(objectTagging);
// 设置进度监听器
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("ProgressEvent: " + progressEvent);
}
});
// 设置其他...
}
};
// 初始化目标 Ks3Client,参见“初始化”文档
Ks3Client dstKs3Client = initKs3Client();
// 复制文件夹
TransferResult transferResult = transferManager.copyDirAcrossRegion("my-bucket", "my-src-prefix/",
"my-bucket-other-region", "my-dst-prefix/", dstKs3Client, uploadFileRequestProvider);
for (TaskResult successFile : transferResult.getSuccessFiles()) {
System.out.println("Copy file success, key: " + successFile.getObjectKey() +
", eTag: " + successFile.getETag() + ", crc64Ecma: " + successFile.getCrc64Ecma());
}
for (ErrorFile errorFile : transferResult.getErrorFiles()) {
System.out.println("Copy file failed, key: " + errorFile.getObjectKey() + ", error message: " + errorFile.getErrorMessage());
}
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
transferManager.shutdown();
}
}public void copyFileListAcrossRegion() {
// 初始化 transferManager,自定义线程数和队列大小
TransferManager transferManager = new TransferManager(ks3Client, 5, 10 * 1024 * 1024);
try {
// 初始化上传文件请求提供器,用于设置复制文件的元数据、存储类型、ACL、标签等
// 上传文件请求提供器是可选的,如果要使用源文件的元数据、存储类型、ACL、标签等,可以不设置
UploadFileRequestProvider uploadFileRequestProvider = new UploadFileRequestProvider() {
@Override
public void provide(UploadFileRequest request) {
// 设置复制文件的分块大小
request.setPartSize(50 * 1024 * 1024);
// 设置复制文件的线程数
request.setTaskNum(5);
// 设置复制文件的元数据,如果没有设置或 MetadataDirective 没有设置为 REPLACE,使用源文件的元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("my-meta-key", "my-meta-value");
// 如果没有设置 MetadataDirective,默认是 COPY,即使用源文件的元数据,如果设置为 REPLACE,则使用自定义的元数据
// objectMetadata.setMetadataDirective("REPLACE");
// 如果没有设置 TaggingDirective,默认是 COPY,即使用源文件的标签,如果设置为 REPLACE,则使用自定义的标签
// objectMetadata.setTaggingDirective("REPLACE");
request.setObjectMetadata(objectMetadata);
// 设置复制文件的存储类型,如果没有设置或 StorageClass 没有设置,使用源文件的存储类型
request.setStorageClass(StorageClass.Standard);
// 设置复制文件的ACL,如果没有设置 CannedAcl 且没有设置 ACL,使用源文件的ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 设置复制文件的自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("my-grantee-id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置复制文件的标签,如果没有设置或 TaggingDirective 没有设置为 REPLACE,使用源文件的标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("my-tag-key", "my-tag-value");
request.setObjectTagging(objectTagging);
// 设置进度监听器
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
System.out.println("ProgressEvent: " + progressEvent);
}
});
// 设置其他...
}
};
// 初始化目标 Ks3Client,参见“初始化”文档
Ks3Client dstKs3Client = initKs3Client();
// 源文件的 key 列表
List<String> srcKeyList = Arrays.asList("my-src-prefix/file1.txt", "my-src-prefix/file2.txt", "my-src-prefix/file3.txt");
// 目标文件的 key 列表
List<String> dstKeyList = Arrays.asList("my-dst-prefix/file1.txt", "my-dst-prefix/file2.txt", "my-dst-prefix/file3.txt");
// 复制文件夹
TransferResult transferResult = transferManager.copyFileListAcrossRegion("my-bucket", srcKeyList,
"my-bucket-other-region", dstKeyList, dstKs3Client, uploadFileRequestProvider);
for (TaskResult successFile : transferResult.getSuccessFiles()) {
System.out.println("Copy file success, key: " + successFile.getObjectKey() + ", eTag: " + successFile.getETag() + ", crc64Ecma: " + successFile.getCrc64Ecma());
}
for (ErrorFile errorFile : transferResult.getErrorFiles()) {
System.out.println("Copy file failed, key: " + errorFile.getObjectKey() + ", error message: " + errorFile.getErrorMessage());
}
} 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());
} catch (Throwable t) {
System.out.println("Throwable occurred: " + t.getMessage());
} finally {
transferManager.shutdown();
}
}
纯净模式
