本文介绍如何将一个存储空间(源存储空间)中的文件复制到同一地域下相同或不同存储空间(目标存储空间)中。
拷贝文件时注意事项如下:
- 用户必须有源Object的读权限及目标Bucket的读写权限。
- 不支持跨地域拷贝。例如不能将华东1(杭州)地域存储空间中的文件拷贝到华北1(青岛)地域。
拷贝小文件
对于小于1 GB的文件,您可以通过ossClient.copyObject方法拷贝文件。此方法有两种参数指定方式:
| 参数指定方式 | 描述 |
|---|---|
| CopyObjectResult copyObject(String sourceBucketName, String sourceKey, String destinationBucketName, String destinationKey) | 允许指定源存储空间和源文件,以及目标存储空间和目标文件。拷贝后,目标文件的内容及元信息与源文件相同,称为简单拷贝。 |
| CopyObjectResult copyObject(CopyObjectRequest copyObjectRequest) | 允许指定目标文件的元信息和拷贝的限制条件。如果拷贝操作的源文件地址和目标文件地址相同,则直接替换源文件的元信息。 |
CopyObjectRequest可设置的参数请参见下表。
| 参数 | 描述 | 方法 |
|---|---|---|
| sourceBucketName | 源存储空间名称。 | setSourceBucketName(String sourceBucketName) |
| sourceKey | 源文件名称。 | setSourceKey(String sourceKey) |
| destinationBucketName | 目标存储空间名称。 | setDestinationBucketName(String destinationBucketName) |
| destinationKey | 目标文件名称。 | setDestinationKey(String destinationKey) |
| newObjectMetadata | 目标文件元信息。 | setNewObjectMetadata(ObjectMetadata newObjectMetadata) |
| matchingETagConstraints | 拷贝的限制条件。如果源文件的ETag值和用户提供的ETag值相等,则执行拷贝操作,否则返回错误。 | setMatchingETagConstraints(List<String> matchingETagConstraints) |
| nonmatchingEtagConstraints | 拷贝的限制条件。如果源文件的ETag值和用户提供的ETag值不相等,则执行拷贝操作,否则返回错误。 | setNonmatchingETagConstraints(List<String> nonmatchingEtagConstraints) |
| unmodifiedSinceConstraint | 拷贝的限制条件。如果传入参数中的时间等于或者晚于文件实际修改时间,则执行拷贝操作,否则返回错误。 | setUnmodifiedSinceConstraint(Date unmodifiedSinceConstraint) |
| modifiedSinceConstraint | 拷贝的限制条件。如果源文件在指定的时间之后被修改过,则执行拷贝操作,否则返回错误。 | setModifiedSinceConstraint(Date modifiedSinceConstraint) |
CopyObjectRequest的参数说明请参见下表。
| 参数 | 描述 | 方法 |
|---|---|---|
| etag | OSS文件唯一性标识。 | String getETag() |
| lastModified | 文件最后修改时间。 | Date getLastModified() |
拷贝小文件有以下几种拷贝形式。
- 简单拷贝
以下代码用于通过简单拷贝将srcexamplebucket中的srcexampleobject.txt文件拷贝到目标存储空间desexamplebucket中的desexampleobject.txt文件。
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 String endpoint = "yourEndpoint"; // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 String accessKeyId = "yourAccessKeyId"; String accessKeySecret = "yourAccessKeySecret"; // 填写源Bucket名称。 String sourceBucketName = "srcexamplebucket"; // 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。 String sourceKey = "srcexampleobject.txt"; // 填写与源Bucket处于同一地域的目标Bucket名称。 String destinationBucketName = "desexamplebucket"; // 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。 String destinationKey = "desexampleobject.txt"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 拷贝文件。 CopyObjectResult result = ossClient.copyObject(sourceBucketName, sourceKey, destinationBucketName, destinationKey); System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified()); // 关闭OSSClient。 ossClient.shutdown(); - 通过CopyObjectRequest拷贝
以下代码用于通过CopyObjectRequest将srcexamplebucket中的srcexampleobject.txt文件拷贝到目标存储空间desexamplebucket中的desexampleobject.txt文件。
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 String endpoint = "yourEndpoint"; // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 String accessKeyId = "yourAccessKeyId"; String accessKeySecret = "yourAccessKeySecret"; // 填写源Bucket名称。 String sourceBucketName = "srcexamplebucket"; // 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。 String sourceKey = "srcexampleobject.txt"; // 填写与源Bucket处于同一地域的目标Bucket名称。 String destinationBucketName = "desexamplebucket"; // 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。 String destinationKey = "desexampleobject.txt"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 创建CopyObjectRequest对象。 CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey); // 设置新的文件元信息。 ObjectMetadata meta = new ObjectMetadata(); meta.setContentType("text/txt"); copyObjectRequest.setNewObjectMetadata(meta); // 复制文件。 CopyObjectResult result = ossClient.copyObject(copyObjectRequest); System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified()); // 关闭OSSClient。 ossClient.shutdown();
拷贝大文件
对于大于1 GB的文件,需要使用分片拷贝(UploadPartCopy)。分片拷贝分为三步:
- 通过ossClient.initiateMultipartUpload初始化分片拷贝任务。
- 通过ossClient.uploadPartCopy进行分片拷贝。除最后一个分片外,其它分片都要大于100KB。
- 通过ossClient.completeMultipartUpload提交分片拷贝任务。
分片拷贝的完整代码请参见GitHub。
以下代码用于通过分片拷贝将srcexamplebucket中的srcexampleobject.txt文件拷贝到目标存储空间desexamplebucket中的desexampleobject.txt文件。
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "yourEndpoint";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写源Bucket名称。
String sourceBucketName = "srcexamplebucket";
// 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。
String sourceKey = "srcexampleobject.txt";
// 填写与源Bucket处于同一地域的目标Bucket名称。
String destinationBucketName = "desexamplebucket";
// 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。
String destinationKey = "desexampleobject.txt";
ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
// 获取被拷贝文件的大小。
long contentLength = objectMetadata.getContentLength();
// 设置分片大小为10 MB。单位为字节。
long partSize = 1024 * 1024 * 10;
// 计算分片总数。
int partCount = (int) (contentLength / partSize);
if (contentLength % partSize != 0) {
partCount++;
}
System.out.println("total part count:" + partCount);
// 初始化拷贝任务。可以通过InitiateMultipartUploadRequest指定目标文件元信息。
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationKey);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
String uploadId = initiateMultipartUploadResult.getUploadId();
// 分片拷贝。
List<PartETag> partETags = new ArrayList<PartETag>();
for (int i = 0; i < partCount; i++) {
// 计算每个分片的大小。
long skipBytes = partSize * i;
long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;
// 创建UploadPartCopyRequest。可以通过UploadPartCopyRequest指定限定条件。
UploadPartCopyRequest uploadPartCopyRequest =
new UploadPartCopyRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
uploadPartCopyRequest.setUploadId(uploadId);
uploadPartCopyRequest.setPartSize(size);
uploadPartCopyRequest.setBeginIndex(skipBytes);
uploadPartCopyRequest.setPartNumber(i + 1);
UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
// 将返回的分片ETag保存到partETags中。
partETags.add(uploadPartCopyResult.getPartETag());
}
// 提交分片拷贝任务。
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
destinationBucketName, destinationKey, uploadId, partETags);
ossClient.completeMultipartUpload(completeMultipartUploadRequest);
// 关闭OSSClient。
ossClient.shutdown();
关于分片拷贝的更多信息,请参见UploadPartCopy。