更新时间:2023-11-08 GMT+08:00
分享

分段复制

开发过程中,您有任何问题可以在github上提交issue,或者在华为云对象存储服务论坛中发帖求助。接口参考文档详细介绍了每个接口的参数和使用方法。

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

// 引入依赖库
require 'vendor/autoload.php';
// 使用源码安装时引入SDK代码库
// require 'obs-autoloader.php';
// 声明命名空间
use Obs\ObsClient;
// 创建ObsClient实例
$obsClient = new ObsClient ( [ 
      //推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险。
      //您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
      'key' => getenv('ACCESS_KEY_ID'),
      'secret' => getenv('SECRET_ACCESS_KEY'),
      'endpoint' => 'https://your-endpoint'
] );

$destBucketName = 'destbucketname';
$destObjectKey = 'destobjectname';
$sourceBucketName = 'sourcebucketname';
$sourceObjectKey = 'sourceobjectname';

// 初始化分段上传任务
$resp = $obsClient->initiateMultipartUpload ( [ 
      'Bucket' => $destBucketName,
      'Key' => $destObjectKey
] );
$uploadId = $resp ['UploadId'];
printf ( "UploadId:%s\n\n", $uploadId );

// 获取大对象信息
$resp = $obsClient->getObjectMetadata ( [ 
      'Bucket' => $sourceBucketName,
      'Key' => $sourceObjectKey 
]);

// 每段复制100MB
$partSize = 100 * 1024 * 1024;

$objectSize = $resp ['ContentLength'];

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

// 执行并发复制段
$promise = null;
$parts = [];
for($i = 0; $i < $partCount; $i ++) {
       $rangeStart = $i * $partSize;
       $rangeEnd = ($i + 1 === $partCount) ? $objectSize - 1 : $rangeStart + $partSize - 1;
       $partNumber = $i + 1;
       $p = $obsClient->copyPartAsync ( [ 
               'Bucket' => $destBucketName,
               'Key' => $destObjectKey,
               'UploadId' => $uploadId,
               'PartNumber' => $partNumber,
               'CopySource' => sprintf ( '%s/%s', $sourceBucketName, $sourceObjectKey ),
               'CopySourceRange' => sprintf ( 'bytes=%d-%d', $rangeStart, $rangeEnd ) 
       ], function ($exception, $resp) use (&$parts, $partNumber) {
              $parts [] = [ 
                           'PartNumber' => $partNumber,
                           'ETag' => $resp ['ETag'] 
              ];
              printf ( "Part#" . strval ( $partNumber ) . " done\n\n" );
       } );
       
       if ($promise === null) {
              $promise = $p;
       }
}

// 等待复制完成
$promise->wait ();

usort ( $parts, function ($a, $b) {
       if ($a ['PartNumber'] === $b ['PartNumber']) {
              return 0;
       }
       return $a ['PartNumber'] > $b ['PartNumber'] ? 1 : - 1;
} );


// 合并段
$resp = $obsClient->completeMultipartUpload ( [ 
        'Bucket' => $destBucketName,
        'Key' => $destObjectKey,
        'UploadId' => $uploadId,
        'Parts' => $parts 
] );
       
printf("Complete to upload multiparts finished, RequestId:%s\n", $resp['RequestId']);

复制段时,使用PartNumber参数指定分段号;使用UploadId参数指定分段上传任务的全局唯一标识;使用CopySource参数指定复制时的源对象信息;使用CopySourceRange参数指定待复制的源对象的字节范围。

相关文档