文档首页 > > SDK参考> Java> 管理对象> 复制对象

复制对象

分享
更新时间: 2019/11/21 GMT+08:00

复制对象即为OBS上已经存在的对象创建一个副本。

您可以通过ObsClient.copyObject来复制对象。复制对象时,可重新指定新对象的属性和设置对象权限,且支持条件复制。

操作限制

  • 用户有待复制的源对象的读权限。
  • 不支持跨区域复制。
  • 待复制的源对象的大小不能超过5GB。小于1GB时,建议使用简单复制;大于1GB时,建议使用分段复制。
  • 如果待复制的源对象是归档存储类型,则必须先取回源对象才能进行复制。

简单复制

以下代码展示了如何进行简单复制:

String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";

// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);

CopyObjectResult result = obsClient.copyObject("sourcebucketname", "sourceobjectname", "destbucketname", "destobjectname");
System.out.println("\t" + result.getEtag());

重写对象属性

以下代码展示了如何在复制对象时重写对象属性:

String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";

// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);

CopyObjectRequest request = new CopyObjectRequest("sourcebucketname", "sourceobjectname", "destbucketname", "destobjectname");
// 设置进行对象属性重写
request.setReplaceMetadata(true);
ObjectMetadata newObjectMetadata = new ObjectMetadata();
newObjectMetadata.setContentType("image/jpeg");
newObjectMetadata.addUserMetadata("property", "property-value");
newObjectMetadata.setObjectStorageClass(StorageClassEnum.WARM);
request.setNewObjectMetadata(newObjectMetadata);
CopyObjectResult result = obsClient.copyObject(request);
System.out.println("\t" + result.getEtag());

CopyObjectRequest.setReplaceMetadata需与CopyObjectRequest.setNewObjectMetadata配合使用。

限定条件复制

复制对象时,可以指定一个或多个限定条件,满足限定条件时则进行复制,否则抛出异常,复制对象失败。

您可以使用的限定条件如下:

参数

作用

OBS Java SDK对应方法

Copy-Source-If-Modified-Since

如果源对象的修改时间晚于该参数值指定的时间,则进行复制,否则抛出异常。

CopyObjectRequest.setIfModifiedSince

Copy-Source-If-Unmodified-Since

如果源对象的修改时间早于该参数值指定的时间,则进行复制,否则抛出异常。

CopyObjectRequest.setIfUnmodifiedSince

Copy-Source-If-Match

如果源对象的ETag值与该参数值相同,则进行复制,否则抛出异常。

CopyObjectRequest.setIfMatchTag

Copy-Source-If-None-Match

如果源对象的ETag值与该参数值不相同,则进行复制,否则抛出异常。

CopyObjectRequest.setIfNoneMatchTag

  • 源对象的ETag值是指源对象数据的MD5校验值。
  • 如果包含Copy-Source-If-Unmodified-Since并且不符合,或者包含Copy-Source-If-Match并且不符合,或者包含Copy-Source-If-Modified-Since并且不符合,或者包含Copy-Source-If-None-Match并且不符合,则复制失败,抛出异常中HTTP状态码为:412 precondition failed。
  • Copy-Source-If-Modified-Since和Copy-Source-If-None-Match可以一起使用;Copy-Source-If-Unmodified-Since和Copy-Source-If-Match可以一起使用。

以下代码展示了如何进行限定条件复制:

String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";

// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);

CopyObjectRequest request = new CopyObjectRequest("sourcebucketname", "sourceobjectname", "destbucketname", "destobjectname");

request.setIfModifiedSince(new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-01"));
request.setIfNoneMatchTag("none-match-etag");

CopyObjectResult result = obsClient.copyObject(request);
System.out.println("\t" + result.getEtag());

重写对象访问权限

以下代码展示了如何在复制对象时重写对象访问权限:

String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";

// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);

CopyObjectRequest request = new CopyObjectRequest("sourcebucketname", "sourceobjectname", "destbucketname", "destobjectname");

// 复制时重写对象访问权限为公共读
request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
CopyObjectResult result = obsClient.copyObject(request);
System.out.println("\t" + result.getEtag());

分段复制

分段复制是分段上传的一种特殊情况,即分段上传任务中的段通过复制OBS指定桶中现有对象(或对象的一部分)来实现。您可以通过ObsClient.copyPart来复制段。以下代码展示了如何使用分段复制模式复制大对象:

String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";

final String destBucketName = "destbucketname";
final String destObjectKey = "destobjectname";
final String sourceBucketName = "sourcebucketname";
final String sourceObjectKey = "sourceobjectname";
// 创建ObsClient实例
final ObsClient obsClient = new ObsClient(ak, sk, endPoint);

// 初始化线程池
ExecutorService executorService = Executors.newFixedThreadPool(20);

// 初始化分段上传任务
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(destBucketName, destObjectKey);
InitiateMultipartUploadResult result = obsClient.initiateMultipartUpload(request);

final String uploadId = result.getUploadId();
System.out.println("\t"+ uploadId + "\n");

// 获取大对象信息
ObjectMetadata metadata = obsClient.getObjectMetadata(sourceBucketName, sourceObjectKey);
// 每段复制100MB
long partSize = 100 * 1024 * 1024L;
long objectSize = metadata.getContentLength();

// 计算需要复制的段数
long partCount = objectSize % partSize == 0 ? objectSize / partSize : objectSize / partSize + 1;

final List<PartEtag> partEtags = Collections.synchronizedList(new ArrayList<PartEtag>());

// 执行并发复制段
for (int i = 0; i < partCount; i++)
{
    // 复制段起始位置
    final long rangeStart = i * partSize;
    // 复制段结束位置
    final long rangeEnd = (i + 1 == partCount) ? objectSize - 1 : rangeStart + partSize - 1;
    // 分段号
    final int partNumber = i + 1;
    executorService.execute(new Runnable()
    {
        
        @Override
        public void run()
        {
            CopyPartRequest request = new CopyPartRequest();
            request.setUploadId(uploadId);
            request.setSourceBucketName(sourceBucketName);
            request.setSourceObjectKey(sourceObjectKey);
            request.setDestinationBucketName(destBucketName);
            request.setDestinationObjectKey(destObjectKey);
            request.setByteRangeStart(rangeStart);
            request.setByteRangeEnd(rangeEnd);
            request.setPartNumber(partNumber);
            CopyPartResult result;
            try
            {
                result = obsClient.copyPart(request);
                System.out.println("Part#" + partNumber + " done\n");
                partEtags.add(new PartEtag(result.getEtag(), result.getPartNumber()));
            }
            catch (ObsException e)
            {
                e.printStackTrace();
            }
        }
    });
}

// 等待复制完成
executorService.shutdown();
while (!executorService.isTerminated())
{
    try
    {
        executorService.awaitTermination(5, TimeUnit.SECONDS);
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
}

// 合并段
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(destBucketName, destObjectKey, uploadId, partEtags);
obsClient.completeMultipartUpload(completeMultipartUploadRequest);
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!

非常感谢您的反馈,我们会继续努力做到更好!

反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨

跳转到云社区