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

批量下载对象

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

您可以通过以下方式批量下载对象:

示例代码

本示例用于批量下载OBS桶中的对象到本地目录。您可以通过列举满足前缀条件的对象, 再以指定并发数并发下载,文件按原Key结构保存到本地目录,适用于批量导出、离线备份等场景。
<?php
// 本示例用于批量下载OBS桶中的对象到本地目录。您可以通过列举满足前缀条件的对象, 再以指定并发数并发下载,文件按原Key结构保存到本地目录,适用于批量导出、离线备份等场景。
// 引入依赖库
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'
] );
$bucketName = 'bucketname';
$localDir = '/tmp/download-dir';
$keyPrefix = 'backup/';

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

while ($isTruncated) {
       $resp = $obsClient->listObjects ( [
              'Bucket' => $bucketName,
              'Prefix' => $keyPrefix,
              'Marker' => $marker,
              // MaxKeys指定每页返回的最大对象数,默认值1000,取值范围1~1000
              'MaxKeys' => 1000                                                                         
        ] );
       if (!empty($resp['Contents'])) {
              foreach ($resp['Contents'] as $content) {
                     $objectsToDownload[] = ['Key' => $content['Key']];
              }
       }
       $isTruncated = $resp['IsTruncated'];
       $marker = $resp['NextMarker'];
}
printf("Found %d objects to download\n\n", count($objectsToDownload));

// 并发下载对象,按原Key结构保存到本地目录
// 生产环境建议增加重试机制,避免网络波动或临时故障导致数据不完整
$successCount = 0;
$failCount = 0;

$promiseGenerator = function () use ($obsClient, $bucketName, $localDir, $objectsToDownload, &$successCount, &$failCount) {
       foreach ($objectsToDownload as $object) {
              $localPath = $localDir . '/' . $object['Key'];
              // 路径遍历防护:检测Key中是否包含..以防止目录穿越
              if (strpos($object['Key'], '..') !== false) {
                     printf("SkipUnsafeKey: Key:%s contains path traversal\n", $object['Key']);
                     $failCount++;
                     continue;
              }
              $localDirPath = dirname($localPath);
              if (!is_dir($localDirPath)) {
                     mkdir($localDirPath, 0755, true);
              }
              yield $obsClient->getObjectAsync ( [
                     'Bucket' => $bucketName,
                     'Key' => $object['Key'],
                     'SaveAsFilepath' => $localPath
              ], function ($exception, $resp) use ($object, &$successCount, &$failCount) {
                     if ($exception === null) {
                            printf ( "Key:%s, ETag:%s, Size:%s\n", $object['Key'], $resp['ETag'], $resp['ContentLength'] );
                            $successCount++;
                     } else {
                            printf ( "DownloadFailed: Key:%s, Status:%d, Message:%s\n", $object['Key'], $exception->getStatusCode(), $exception->getExceptionMessage() );
                            $failCount++;
                     }
              } );
       }
};

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

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

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