更新时间:2026-06-30 GMT+08:00

批量复制对象

开发过程中,您有任何问题可以在GitHub上提交issue接口参考文档详细介绍了每个接口的参数和使用方法。

示例代码

本示例用于批量复制OBS桶中的对象到目标桶。您可以通过列举满足前缀条件的对象, 再以指定并发数批量复制到目标桶,目标Key通过前缀替换生成,支持跨桶复制或同桶备份,适用于数据迁移、备份等场景。

<?php
// 引入依赖库
require 'vendor/autoload.php';
// 使用源码安装时引入SDK代码库
// require 'obs-autoloader.php';
// 声明命名空间
use Obs\ObsClient;
// 创建ObsClient实例
$obsClient = new ObsClient ( [
      //推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险。
      //您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/intl/zh-cn/usermanual-ca/ca_01_0003.html
      'key' => getenv('ACCESS_KEY_ID'),
      'secret' => getenv('SECRET_ACCESS_KEY'),
      // endpoint填写Bucket对应的Endpoint, 此处以中国-香港为例,其他地区请按实际情况填写。
       'endpoint' => "obs.ap-southeast-1.myhuaweicloud.com",
      'signature' => 'obs'
] );

$sourceBucket = 'sourcebucketname';
$destBucket = 'destbucketname';
$sourcePrefix = 'data/';
$destPrefix = 'backup/';
$concurrency = 5;

// 列举满足前缀的对象
$isTruncated = true;
$marker = null;
$objectsToCopy = [];

while ($isTruncated) {
       $resp = $obsClient->listObjects ( [
              'Bucket' => $sourceBucket,
              'Prefix' => $sourcePrefix,
              'Marker' => $marker
       ] );
       if (!empty($resp['Contents'])) {
              foreach ($resp['Contents'] as $content) {
                     // 目标Key通过前缀替换生成
                     $destKey = $destPrefix . substr($content['Key'], strlen($sourcePrefix));
                     // 跳过目录对象本身(Key等于sourcePrefix时destKey为空)
                     if ($destKey === '' || substr($destKey, -1) === '/') {
                            continue;
                     }
                     $objectsToCopy[] = ['SourceKey' => $content['Key'], 'DestKey' => $destKey, 'Size' => $content['Size']];
              }
       }
       $isTruncated = $resp['IsTruncated'];
       $marker = $resp['NextMarker'];
}
printf("Found %d objects to copy\n\n", count($objectsToCopy));

// 并发复制对象
// 生产环境建议增加重试机制,避免网络波动或临时故障导致复制不完整 
// copyObject单次操作仅支持复制不超过5GB的对象,超过5GB的对象请使用多段复制(Upload Part Copy)
// 源桶和目标桶须在同一区域,跨区域复制请先配置跨区域复制规则
// 如需复制指定版本,请在CopySource中添加版本ID,格式为bucket/key?versionId=xxx
// 复制前请确认目标桶中无同名对象,否则copyObject将直接覆盖

$successCount = 0;
$failCount = 0;

$promiseGenerator = function () use ($obsClient, $sourceBucket, $destBucket, $objectsToCopy, &$successCount, &$failCount) {
       foreach ($objectsToCopy as $object) {
              yield $obsClient->copyObjectAsync ([
                     'Bucket' => $destBucket,
                     'Key' => $object['DestKey'],
                     // CopySource中的Key含特殊字符时需URL编码
                     'CopySource' => $sourceBucket . '/' . rawurlencode($object['SourceKey']),
                     // 可选:指定目标对象的存储类型,如 'StorageClass' => ObsClient::StorageClassStandard
              ], function ($exception, $resp) use ($object, &$successCount, &$failCount) {
                     if ($exception === null) {
                            printf ( "CopyTo:%s, RequestId:%s\n", $object['DestKey'], $resp['RequestId'] );
                            $successCount++;
                     } else {
                            printf ( "CopyFailed: Key:%s, Status:%d, Message:%s\n", $object['SourceKey'], $exception->getStatusCode(), $exception->getExceptionMessage() );
                            $failCount++;
                     }
              } );
       }
};

$eachPromise = new EachPromise($promiseGenerator(), [
       'concurrency' => $concurrency
]);

$eachPromise->promise()->wait();

printf("\nResult: success=%d, fail=%d\n", $successCount, $failCount);