更新时间:2026-08-28 GMT+08:00
批量恢复归档存储对象
本示例用于批量恢复归档存储中的对象。您可以指定待恢复的对象Key列表、恢复速率(Expedited/Standard)和保留天数,并发发起恢复请求,适用于大规模归档数据的批量恢复场景。
#import <Foundation/Foundation.h>
#import <OBS/OBS.h>
#pragma mark - Result Model
@interface BatchRestoreResult : NSObject
@property (nonatomic, copy) NSString *objectKey;
@property (nonatomic, assign) BOOL success;
@property (nonatomic, strong) NSError *error;
@property (nonatomic, copy) NSString *httpStatusCode;
@end
@implementation BatchRestoreResult
@end
#pragma mark - Batch Restorer
@interface BatchArchiveRestorer : NSObject
@property (nonatomic, strong) OBSClient *client;
@property (nonatomic, copy) NSString *bucketName;
@property (nonatomic, assign) NSInteger concurrentCount;
@property (nonatomic, assign) OBSRestoreTier restoreTier;
@property (nonatomic, assign) NSInteger storeDays;
@property (nonatomic, strong) NSMutableArray<BatchRestoreResult *> *results;
@property (nonatomic, strong) dispatch_queue_t resultQueue;
- (instancetype)initWithClient:(OBSClient *)client
bucketName:(NSString *)bucketName
concurrentCount:(NSInteger)concurrentCount
restoreTier:(OBSRestoreTier)restoreTier
storeDays:(NSInteger)storeDays;
- (void)restoreObjects:(NSArray<NSString *> *)objectKeys
waitUntilDone:(BOOL)wait;
@end
@implementation BatchArchiveRestorer
- (instancetype)initWithClient:(OBSClient *)client
bucketName:(NSString *)bucketName
concurrentCount:(NSInteger)concurrentCount
restoreTier:(OBSRestoreTier)restoreTier
storeDays:(NSInteger)storeDays {
self = [super init];
if (self) {
_client = client;
_bucketName = bucketName;
_concurrentCount = MIN(concurrentCount > 0 ? concurrentCount : 3, 10);
_restoreTier = restoreTier;
_storeDays = (storeDays > 0 && storeDays <= 30) ? storeDays : 1;
_results = [NSMutableArray array];
_resultQueue = dispatch_queue_create("com.obs.batchrestore.result", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)restoreObjects:(NSArray<NSString *> *)objectKeys
waitUntilDone:(BOOL)wait {
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(self.concurrentCount);
dispatch_queue_t queue = dispatch_queue_create("com.obs.batchrestore", DISPATCH_QUEUE_CONCURRENT);
NSString *tierStr = (self.restoreTier == OBSRestoreTierExpedited) ? @"Expedited" : @"Standard";
NSLog(@"[BatchRestore] Starting %lu restores, concurrency: %ld, tier: %@, days: %ld",
(unsigned long)objectKeys.count, (long)self.concurrentCount, tierStr, (long)self.storeDays);
for (NSString *objectKey in objectKeys) {
dispatch_group_enter(group);
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 300 * NSEC_PER_SEC));
[self restoreObject:objectKey completion:^{
dispatch_semaphore_signal(semaphore);
dispatch_group_leave(group);
}];
});
}
if (wait) {
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 300 * NSEC_PER_SEC));
[self printSummary];
}
}
- (void)restoreObject:(NSString *)objectKey completion:(void (^)(void))completion {
OBSRestoreObjectRequest *request = [[OBSRestoreObjectRequest alloc] initWithBucketName:self.bucketName
objectKey:objectKey
storeDays:@(self.storeDays)];
request.restoreTier = self.restoreTier;
__weak typeof(self) weakSelf = self; __strong typeof(weakSelf) strongSelf = weakSelf; if (!strongSelf) return; [self.client restoreObject:request completionHandler:^(OBSRestoreObjectResponse *response, NSError *error) {
BatchRestoreResult *result = [[BatchRestoreResult alloc] init];
result.objectKey = objectKey;
result.error = error;
result.success = (error == nil);
result.httpStatusCode = response.statusCode ?: @"-";
if (error) {
NSLog(@"[Restore] FAILED - %@ : %@", objectKey, error.localizedDescription);
} else {
NSLog(@"[Restore] SUCCESS - %@ (HTTP %@)", objectKey, result.httpStatusCode);
}
dispatch_sync(strongSelf.resultQueue, ^{ [strongSelf.results addObject:result]; });
if (completion) completion();
}];
}
- (void)printSummary {
NSInteger success = 0, failure = 0;
for (BatchRestoreResult *r in self.results) {
if (r.success) success++;
else failure++;
}
NSLog(@"\n========== Batch Restore Summary ==========");
NSLog(@"Total: %lu | Success: %ld | Failed: %ld", (unsigned long)self.results.count, (long)success, (long)failure);
if (failure > 0) {
NSLog(@"Failed items:");
for (BatchRestoreResult *r in self.results) {
if (!r.success) {
NSLog(@" - %@ : %@", r.objectKey, r.error.localizedDescription);
}
}
}
NSLog(@"============================================\n");
}
@end
#pragma mark - Entry Point
int main(int argc, const char * argv[]) {
@autoreleasepool {
// === Configuration ===
NSString *endPoint = @"https://your-endpoint";
// 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量AccessKeyID和SecretAccessKey。
// 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
if (ak_env == NULL || sk_env == NULL) {
NSLog(@"Error: AccessKeyID or SecretAccessKey environment variable not set");
return 1;
}
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];
NSString *bucketName = @"your-bucket-name";
NSInteger concurrentCount = 3; // Adjust as needed
// Restore options
OBSRestoreTier restoreTier = OBSRestoreTierStandard; // or OBSRestoreTierExpedited
NSInteger storeDays = 1; // 1-30 days
// Objects to restore (must be in Archive or Cold storage class)
NSArray<NSString *> *objectKeys = @[
@"archive_folder/doc1.pdf",
@"archive_folder/doc2.jpg",
@"archive_folder/doc3.zip",
@"archive_folder/doc4.mp4",
@"archive_folder/doc5.tar"
];
// === Initialize OBS Client ===
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
OBSClient *client = [[OBSClient alloc] initWithConfiguration:conf];
// === Batch Restore ===
BatchArchiveRestorer *restorer = [[BatchArchiveRestorer alloc] initWithClient:client
bucketName:bucketName
concurrentCount:concurrentCount
restoreTier:restoreTier
storeDays:storeDays];
[restorer restoreObjects:objectKeys waitUntilDone:YES];
}
return 0;
} 父主题: 对象基础操作