Object管理
上传Object
最简单的上传
-
基本流程
- 创建BOSClient类的实例。
- 调用BOSClient putObject方法,可以通过如下二种方式上传Object:文件、二进制数据的形式。
- 对返回的BOSPutObjectResponse类型实例,可以执行获取eTag操作。
-
示例代码
BOSObjectContent* content = [[BOSObjectContent alloc] init]; // 以文件方式 content.objectData.file = @"<file path>"; // 或者以二进制数据方式 NSData* data = [[NSData alloc] init]; content.objectData.data = data; BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.objectContent = content; __block BOSPutObjectResponse* response = nil; BCETask* task = [client putObject:request]; task.then(^(BCEOutput* output) { if (output.progress) { NSLog(@"put object progress is %@", output.progress); } if (output.response) { response = (BOSPutObjectResponse*)output.response; NSLog(@"put object success!"); } if (output.error) { NSLog(@"put object failure"); } }); [task waitUtilFinished];
说明:Object以文件的形式上传到BOS中,putObject函数支持不超过5GB的Object上传。在putObject请求处理成功后,BOS会在Header中返回Object的ETag作为文件标识。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSObjectContent* content = [[BOSObjectContent alloc] init]; // 以文件方式 content.objectData.file = @"<file path>"; // 或者以二进制数据方式 NSData* data = [[NSData alloc] init]; content.objectData.data = data; BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.objectContent = content; __block BOSPutObjectResponse* response = nil; BCETask* task = [client putObject:request]; task.then(^(BCEOutput* output) { if (output.progress) { NSLog(@"put object progress is %@", output.progress); } if (output.response) { response = (BOSPutObjectResponse*)output.response; NSLog(@"put object success!"); } if (output.error) { NSLog(@"put object failure"); } }); [task waitUtilFinished]; }
设定Object的Http Header
BOS支持您在上传object时设定Http Header。
-
基本流程
- 创建BOSObjectMetadata类的实例。
- 设定BOSObjectMetadata实例的contentEncoding/contentType/contentDisposition等字段。
- 将BOSObjectMetadata实例设置到BOSPutObjectRequest的objectContent.metadata字段上。
-
示例代码
BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; metadata.contentEncoding = @"<encoding>"; metadata.contentDisposition = @"<content disposition>"; content.metadata = metadata;
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSObjectContent* content = [[BOSObjectContent alloc] init]; // 以文件方式 content.objectData.file = @"<file path>"; // 或者以二进制数据方式 NSData* data = [[NSData alloc] init]; content.objectData.data = data; BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; metadata.contentEncoding = @"<encoding>"; metadata.contentDisposition = @"<content disposition>"; content.metadata = metadata; BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<Objectname>"; request.objectContent = content; __block BOSPutObjectResponse* response = nil; BCETask* task = [client putObject:request]; task.then(^(BCEOutput* output) { if (output.progress) { NSLog(@"put object progress is %@", output.progress); } if (output.response) { response = (BOSPutObjectResponse*)output.response; NSLog(@"put object success!"); } if (output.error) { NSLog(@"put object failure"); } }); [task waitUtilFinished]; }
用户自定义元数据
BOS支持用户自定义元数据来对Object进行描述。
-
基本流程
- 创建BOSObjectMetadata类的实例。
- 将自定义元数据字典设置到BOSObjectMetadata的userMetadata字段。
-
示例代码
BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; metadata.contentEncoding = @"<encoding>"; metadata.contentDisposition = @"<content disposition>"; content.metadata = metadata; NSDictionary* customMetadata = @{ @"name" : @"my-data" }; content.metadata.userMetadata = customMetadata;
说明:在上面代码中,用户自定义了一个名字为”name”,值为”my-data”的元数据。当用户下载此Object的时候,此元数据也可以一并得到。一个Object可以有多个类似的参数,但所有的User Meta总大小不能超过2KB。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSObjectContent* content = [[BOSObjectContent alloc] init]; // 以文件方式 content.objectData.file = @"<file path>"; // 或者以二进制数据方式 NSData* data = [[NSData alloc] init]; content.objectData.data = data; BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; metadata.contentEncoding = @"<encoding>"; metadata.contentDisposition = @"<content disposition>"; content.metadata = metadata; NSDictionary* customMetadata = @{ @"name" : @"my-data" }; content.metadata.userMetadata = customMetadata; BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.objectContent = content; __block BOSPutObjectResponse* response = nil; BCETask* task = [client putObject:request]; task.then(^(BCEOutput* output) { if (output.progress) { NSLog(@"put object progress is %@", output.progress); } if (output.response) { response = (BOSPutObjectResponse*)output.response; NSLog(@"put object success!"); } if (output.error) { NSLog(@"put object failure"); } }); [task waitUtilFinished]; }
查看Bucket中的Object
简单查询
查看Bucket中Object列表。
-
基本流程
- 创建BOSClient类的实例。
- 执行BOSClient listObjects方法,会返回BOSListObjectsResponse类的实例。
- 可以对BOSListObjectsResponse类型的contents字段进行枚举,获取key/lastModified/eTag/size/owner。
-
示例代码
BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init]; listObjRequest.bucket = @"<bucketname>"; __block BOSListObjectsResponse* listObjResponse = nil; BCETask* task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; for (BOSObjectInfo* object in listObjResponse.contents) { NSLog(@"the object key is %@", object.key); NSLog(@"the object lastModified is %@", object.lastModified); NSLog(@"the object eTag is %@", object.eTag); NSLog(@"the object size is %llu", object.size); NSLog(@"the object owner id is %@", object.owner.ownerID); } } if (output.error) { NSLog(@"list objects failure"); } }); [task waitUtilFinished];
说明: listObjects方法返回BOSListObjectsResponse对象,BOSListObjectsResponse对象包含了此次listObject请求的返回结果。用户可以通过BOSListObjectsResponse中的contents属性获取所有Object的描述信息。
- 默认情况下,如果Bucket中的Object数量大于1000,则只会返回1000个Object,并且返回结果中isTruncated值为YES,并返回nextMarker做为下次读取的起点。
- 若想获取更多的Object,可以使用marker参数分次读取,请参考扩展查询。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init]; listObjRequest.bucket = @"<bucketname>"; __block BOSListObjectsResponse* listObjResponse = nil; BCETask* task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; for (BOSObjectInfo* object in listObjResponse.contents) { NSLog(@"the object key is %@", object.key); NSLog(@"the object lastModified is %@", object.lastModified); NSLog(@"the object eTag is %@", object.eTag); NSLog(@"the object size is %llu", object.size); NSLog(@"the object owner id is %@", object.owner.ownerID); } } if (output.error) { NSLog(@"list objects failure"); } }); [task waitUtilFinished]; }
扩展查询
用户可以通过设置BOSListObjectsResquest参数来完成更多扩展查询操作设置。BOSListObjectsResquest中可以设置的扩展参数如下:
参数名称 | 说明 | 默认值 |
---|---|---|
maxKeys | 设定此次返回Object的最大个数,不可超过1000。 | 1000 |
prefix | 设定objectKey的前缀,前缀是指objectKey包含并以prefix的值作为开始。通常与delimiter配合在查询模拟文件夹中使用。 | - |
delimiter | 是一个分隔符,用来对objectKey进行分层。通常与prefix配合在查询模拟文件夹中使用。从prefix开始到第一次出现delimiter字符之间的objectKey称为:commonPrefixes。 | - |
marker | 是一个字符串,用来设定返回结果的起始位置。设定marker值之后,返回的Object会从marker值之后按字母排序开始返回。 | - |
-
基本流程
- 创建BOSListObjectsResquest类的实例。
- 设置BOSListObjectsResquest的delimiter/marker/prefix/maxKeys等字段,实现更多的扩展查询操作。
- 创建BOSClient类的实例,执行listObjects。
-
示例代码
BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init]; listObjRequest.bucket = @"<bucketname>"; listObjRequest.marker = @"<marker>"; __block BOSListObjectsResponse* listObjResponse = nil; BCETask* task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; for (BOSObjectInfo* object in listObjResponse.contents) { NSLog(@"the object key is %@", object.key); NSLog(@"the object lastModified is %@", object.lastModified); NSLog(@"the object eTag is %@", object.eTag); NSLog(@"the object size is %llu", object.size); NSLog(@"the object owner id is %@", object.owner.ownerID); } } if (output.error) { NSLog(@"list objects failure"); } }); [task waitUtilFinished];
-
完整示例
示例一:
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init]; listObjRequest.bucket = @"<bucketname>"; listObjRequest.marker = @"<marker>"; __block BOSListObjectsResponse* listObjResponse = nil; BCETask* task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; for (BOSObjectInfo* object in listObjResponse.contents) { NSLog(@"the object key is %@", object.key); NSLog(@"the object lastModified is %@", object.lastModified); NSLog(@"the object eTag is %@", object.eTag); NSLog(@"the object size is %llu", object.size); NSLog(@"the object owner id is %@", object.owner.ownerID); } } if (output.error) { NSLog(@"list objects failure"); } }); [task waitUtilFinished]; }
示例二:使用nextMarker的完整示例。
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init]; listObjRequest.bucket = @"<bucketname>"; listObjRequest.marker = @"<marker>"; __block BOSListObjectsResponse* listObjResponse = nil; BCETask* task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; } if (output.error) { NSLog(@"list objects failure"); } }); [task waitUtilFinished]; if (listObjResponse != nil) { listObjRequest.marker = listObjResponse.nextMarker; task = [client listObjects:listObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { listObjResponse = (BOSListObjectsResponse*)output.response; for (BOSObjectInfo* object in listObjResponse.contents) { NSLog(@"the object key is %@", object.key); NSLog(@"the object lastModified is %@", object.lastModified); NSLog(@"the object eTag is %@", object.eTag); NSLog(@"the object size is %llu", object.size); NSLog(@"the object owner id is %@", object.owner.ownerID); } } }); } }
查询模拟文件夹
由于BOS本身是一个(<Key>,<Value>
)的存储系统,所以原则上并不会存在“文件夹”的概念,但您可以通过delimiter
和prefix
参数的配合进行文件夹功能模拟。
假设Bucket中有5个文件:bos.jpg,fun/,fun/test.jpg,fun/movie/001.avi,fun/movie/007.avi,可以把 “/” 符号作为分隔符模拟文件夹。
递归列出模拟文件夹下所有文件
可以通过设置prefix
参数来获取某个模拟文件夹下所有的文件:
BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
listObjRequest.bucket = @"<bucketname>";
listObjRequest.prefix = @"fun/";
__block BOSListObjectsResponse* listObjResponse = nil;
BCETask* task = [client listObjects:listObjRequest];
task.then(^(BCEOutput* output) {
if (output.response) {
listObjResponse = (BOSListObjectsResponse*)output.response;
for (BOSObjectInfo* object in listObjResponse.contents) {
NSLog(@"%@", object.key);
}
}
});
[task waitUtilFinished];
输出:
Objects:
fun/
fun/movie/001.avi
fun/movie/007.avi
fun/test.jpg
查看模拟文件夹下的文件和子文件夹
在prefix
和delimiter
结合的情况下,可以列出模拟文件夹下的文件和子文件夹:
BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
listObjRequest.bucket = @"<bucketname>";
// 指定"/"为模拟文件夹的分隔符
listObjRequest.delimiter = @"/";
// 列出fun文件夹下的所有文件和子文件夹
listObjRequest.prefix = @"fun/";
__block BOSListObjectsResponse* listObjResponse = nil;
BCETask* task = [client listObjects:listObjRequest];
task.then(^(BCEOutput* output) {
if (output.response) {
listObjResponse = (BOSListObjectsResponse*)output.response;
}
if (output.error) {
NSLog(@"list objects failure");
}
});
[task waitUtilFinished];
// 遍历所有Object
NSLog(@"Objects:");
for (BOSObjectInfo* object in listObjResponse.contents) {
NSLog(@"%@", object.key);
}
// 遍历所有CommonPrefix
NSLog(@"CommonPrefixs:");
for (NSString* commonPrefix in listObjResponse.commonPrefixes) {
NSLog(@"%@", commonPrefix);
}
输出:
Objects:
fun/
fun/test.jpg
CommonPrefixs:
fun/movie/
说明: 返回的结果中,
contents
的列表中给出的是fun文件夹下的文件。而commonPrefixs
的列表中给出的是fun文件夹下的所有子文件夹。可以看出fun/movie/001.avi
,fun/movie/007.avi
两个文件并没有被列出来,因为它们属于fun
文件夹下的movie
子文件夹下的文件。
获取Object
简单的获取Object
用户可以通过如下代码将Object读取到内存中。
-
基本流程
- 创建BOSClient类的实例。
- 执行BOSClient getObject方法,会返回BOSGetObjectResponse实例。
- 访问BOSGetObjectResponse示例的objectContent.objectData.data属性,获取数据。
-
示例代码
__block BOSGetObjectResponse* getObjResponse = nil; BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init]; getObjRequest.bucket = @"<bucketname>"; getObjRequest.key = @"<objectname>"; BCETask* task = [client getObject:getObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { getObjResponse = (BOSGetObjectResponse*)output.response; NSLog(@"get object success!"); } if (output.error) { NSLog(@"get object failure with %@", outpu****t.error); } if (output.progress) { NSLog(@"the get object progress is %@", output.progress); } }); [task waitUtilFinished]; // 获取内存中的数据 NSData* data = getObjResponse.objectContent.objectData.data;
注意:
- BOSObjectContent中包含了Object的各种信息,包含Object所在的Bucket、Object的名称、MetaData以及数据存储。
- BOSObjectMetadata中包含了Object上传时定义的ETag,Http Header以及自定义的元数据。
- 通过BOSObjectContent的objectData属性,获取到Object的数据。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; __block BOSGetObjectResponse* getObjResponse = nil; BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init]; getObjRequest.bucket = @"<bucketname>"; getObjRequest.key = @"<objectname>"; BCETask* task = [client getObject:getObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { getObjResponse = (BOSGetObjectResponse*)output.response; NSLog(@"get object success!"); } if (output.error) { NSLog(@"get object failure with %@", output.error); } if (output.progress) { NSLog(@"the get object progress is %@", output.progress); } }); [task waitUtilFinished]; NSData* data = getObjResponse.objectContent.objectData.data; }
下载Object的一部分内容
-
基本流程
- 创建BOSGetObjectRequest类的实例。
- BOSGetObjectRequestt实例的rangeStart和/或rangeEnd字段。
- 执行client getObject操作。
-
示例代码
__block BOSGetObjectResponse* getObjResponse = nil; BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init]; getObjRequest.bucket = @"<bucketname>"; getObjRequest.key = @"<objectname>"; // 获取前100个字节 getObjRequest.rangeStart = @"0"; getObjRequest.rangeEnd = @"99"; BCETask* task = [client getObject:getObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { getObjResponse = (BOSGetObjectResponse*)output.response; NSLog(@"get object success!"); } if (output.error) { NSLog(@"get object failure with %@", output.error); } if (output.progress) { NSLog(@"the get object progress is %@", output.progress); } }); [task waitUtilFinished]; NSData* data = getObjResponse.objectContent.objectData.data;
说明:用户可以用此功能实现文件的分段下载和断点续传。
下载Object到指定路径
用户可以通过如下代码直接将Object下载到指定路径。
-
基本流程
- 创建BOSGetObjectRequest类的实例。
- 设置要保存的文件名到BOSGetObjectRequest实例的file字段。
- 执行client getObject操作。
- Object可以直接下载到指定路径。
-
示例代码
__block BOSGetObjectResponse* getObjResponse = nil; BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init]; getObjRequest.bucket = @"<bucketname>"; getObjRequest.key = @"<objectname>"; // 设置保存到的文件路径 getObjRequest.file = @"<file>"; BCETask* task = [client getObject:getObjRequest]; task.then(^(BCEOutput* output) { if (output.response) { getObjResponse = (BOSGetObjectResponse*)output.response; NSLog(@"get object success!"); } if (output.error) { NSLog(@"get object failure with %@", output.error); } if (output.progress) { NSLog(@"the get object progress is %@", output.progress); } }); [task waitUtilFinished];
获取Object的storageClass
Object的storage class属性分为STANDARD(标准存储), STANDARD_IA(低频存储)和COLD(冷存储)。
示例代码
__block BOSGetObjectMetadataResponse* getObjMetaResponse = nil;
BCETask* task = [client getObjectMetadata:@"<bucketname>" objectKey:@"<objectname>"];
task.then(^(BCEOutput* output) {
if (output.response) {
getObjMetaResponse = (BOSGetObjectMetadataResponse*)output.response;
NSString storageClass = getObjMetaResponse.storageClass;
NSLog(@"get object storageClass success!");
}
if (output.error) {
NSLog(@"get object storageClass failure");
}
});
[task waitUtilFinished];
只获取ObjectMetadata
通过getObjectMetadata 方法可以只获取 Object metadata 而不获取Object的实体。
-
示例代码
__block BOSGetObjectMetadataResponse* getObjMetaResponse = nil; BCETask* task = [client getObjectMetadata:@"<bucketname>" objectKey:@"<objectname>"]; task.then(^(BCEOutput* output) { if (output.response) { getObjMetaResponse = (BOSGetObjectMetadataResponse*)output.response; NSLog(@"get object metadata success!"); } if (output.error) { NSLog(@"get object metadata failure"); } }); [task waitUtilFinished];
获取Object的URL
您可以通过如下代码获取指定Object的URL,该功能通常用于您将Object的URL临时分享给其他用户的场景。
-
基本流程
- 创建BOSClient类的实例。
- 执行BOSClient generatePresignedUrl方法。
- 返回一个Object的URL。
-
示例代码
__block BOSGeneratePresignedUrlResponse *generateObjetUrlRes = nil; BCEOutput_ output = [client generatePresignedUrl:@"<bucketname>" objectKey:@"<objectname>" expirationInSeconds:<ExpirationInSeconds>]; if (output.response) { generateObjetUrlRes = (BOSGeneratePresignedUrlResponse_)output.response; NSLog(@"get url success, the usrlstting is : %@", [generateObjetUrlRes.objectUrl absoluteString]); } if (output.error) { NSLog(@"get url failure, error : %@:", output.error); }
说明: ExpirationInSeconds为指定的URL有效时长,时间从当前时间算起,为可选参数,不配置时系统默认值为1800秒。如果要设置为永久不失效的时间,可以将ExpirationInSeconds参数设置为 -1,不可设置为其他负数。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; __block BOSGeneratePresignedUrlResponse *generateObjetUrlRes = nil; BCEOutput* output = [client generatePresignedUrl:@"<bucketname>" objectKey:@"<objectname>" expirationInSeconds:<ExpirationInSeconds>]; if (output.response) { generateObjetUrlRes = (BOSGeneratePresignedUrlResponse*)output.response; NSLog(@"get url success, the usrlstting is : %@", [generateObjetUrlRes.objectUrl absoluteString]); } if (output.error) { NSLog(@"get url failure, error : %@:", output.error); } }
删除Object
-
基本流程
- 创建BOSClient类的实例。
- 执行BOSClient deleteObject方法。
- 若操作失败后产生错误。
-
示例代码
__block BOSDeleteObjectResponse* response = nil; BCETask* task = [client deleteObject:@"<bucketname>" objectKey:@"<objectname>"]; task.then(^(BCEOutput* output) { if (output.response) { response = (BOSDeleteObjectResponse*)output.response; NSLog(@"delete obj success!"); } if (output.error) { NSLog(@"delete obj failure"); } }); [task waitUtilFinished];
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; __block BOSDeleteObjectResponse* response = nil; BCETask* task = [client deleteObject:@"<bucketname>" objectKey:@"<objectname>"]; task.then(^(BCEOutput* output) { if (output.response) { response = (BOSDeleteObjectResponse*)output.response; NSLog(@"delete obj success!"); } if (output.error) { NSLog(@"delete obj failure"); } }); [task waitUtilFinished]; }
拷贝Object
简单拷贝Object
-
基本流程
- 创建BOSClient类的实例。
- 执行BOSClient copyObject方法。
- 返回BOSCopyObjectResponse类实例,可通过eTag/lastModified等属性获取eTag和最后修改时间。
-
示例代码
BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.source = @"<sourceBucket>/<sourceObject"; __block BOSCopyObjectResponse* response = nil; BCETask* task = [client copyObject:request]; task.then(^(BCEOutput* output) { if (output.response) { response = (BOSCopyObjectResponse*)output.response; NSLog(@"copy obj success!"); } if (output.error) { NSLog(@"copy obj failure"); } }); [task waitUtilFinished];
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.source = @"<sourceBucket>/<sourceObject"; __block BOSCopyObjectResponse* response = nil; BCETask* task = [client copyObject:request]; task.then(^(BCEOutput* output) { if (output.response) { response = (BOSCopyObjectResponse*)output.response; NSLog(@"copy obj success!"); } if (output.error) { NSLog(@"copy obj failure"); } }); [task waitUtilFinished]; }
说明:copyObject 方法返回一个
BOSCopyObjectResponse
对象,该对象中包含了新Object的ETag和修改时间。
指定条件拷贝Object
您也可以通过指定条件来实现Object的拷贝。该功能一般用于如下场景:
- Copy一个Object但重新设置meta。
- 重置某个现有Object的meta(把源和目标设置为同一个Object)。
- 当源Object的eTag与指定的eTag相同时复制;
- 当源Object的eTag与指定的eTag不相同时复制;
- 当源Object的在指定的时间后没有被修改时复制;
- 当源Object的在指定的时间后被修改过时复制;
具体内容如下:
-
基本流程
- 创建BOSCopyObjectRequest类的实例,传入
<source>
,<ifMatchEtag>
,<ifNotMatchEtag>
,<ifModifiedSince>
,<ifUnmodifiedSince>
,<metadataDirective>
参数。 - 返回BOSCopyObjectResponse类实例,可通过eTag/lastModified属性获取eTag和最后修改时间。
- 创建BOSCopyObjectRequest类的实例,传入
-
示例代码
BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init]; request.bucket = @"<bucketname>"; request.key = @"<objectname>"; request.source = @"<sourceBucket>/<sourceObject"; request.metadataDirective = @"replace"; request.ifModifiedSince = @"Wed, 01 Mar 2006 12:00:00 GMT"; __block BOSCopyObjectResponse* response = nil; BCETask* task = [client copyObject:request]; task.then(^(BCEOutput* output) { if (output.response) { response = (BOSCopyObjectResponse*)output.response; NSLog(@"copy obj success!"); } if (output.error) { NSLog(@"copy obj failure"); } }); [task waitUtilFinished];
说明:
BOSCopyObjectRequest
允许用户修改目的Object的ObjectMeta,同时也提供MatchingETagConstraints
参数的设定。
Object的分块上传
除了通过putObject()方法上传文件到BOS以外,BOS还提供了另外一种上传模式:分块上传(Multipart Upload)。用户可以在如下的应用场景内(但不仅限于此),使用分块上传模式,如:
- 需要支持断点上传。
- 上传超过5GB大小的文件。
- 网络条件较差,和BOS的服务器之间的连接经常断开。
- 需要流式地上传文件。
- 上传文件之前,无法确定上传文件的大小。
分块完成Multipart Upload
假设有一个文件,本地路径为/path/to/file.zip
,由于文件比较大,使用分块上传其传输到BOS中。
-
基本流程
- 初始化Multipart Upload。
- 上传分块。
- 完成分块上传。
初始化Multipart Upload
使用initiateMultipartUpload
方法来初始化一个分块上传事件:
-
示例代码
BOSInitiateMultipartUploadRequest* initMPRequest = [[BOSInitiateMultipartUploadRequest alloc] init]; initMPRequest.bucket = @"<bucketname>"; initMPRequest.key = @"<objectname>"; initMPRequest.contentType = @"<content type>"; __block BOSInitiateMultipartUploadResponse* initMPResponse = nil; BCETask* task = [client initiateMultipartUpload:initMPRequest]; task.then(^(BCEOutput* output) { if (output.response) { initMPResponse = (BOSInitiateMultipartUploadResponse*)output.response; NSLog(@"initiate multipart upload success!"); } if (output.error) { NSLog(@"initiate multipart upload failure"); } }); [task waitUtilFinished]; NSString* uploadID = initMPResponse.uploadId;
说明:
initiateMultipartUpload
的返回结果中含有uploadId
,它是区分分块上传事件的唯一标识,在后面的操作中,我们将用到它。
上传分块
将文件分块上传。
-
示例代码
// 计算分块个数 NSString* file = @"/path/to/file.zip"; NSDictionary<NSString*, id>* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil]; uint64_t fileSize = attr.fileSize; uint64_t partSize = 1024 * 1024 * 5L; uint64_t partCount = fileSize / partSize; if (fileSize % partSize != 0) { ++partCount; } NSMutableArray<BOSPart*>* parts = [NSMutableArray array]; NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file.zip"]; for (uint64_t i = 0; i < partCount; ++i) { // seek uint64_t skip = partSize * i; [handle seekToFileOffset:skip]; uint64_t size = (partSize < fileSize - skip) ? partSize : fileSize - skip; // data NSData* data = [handle readDataOfLength:size]; // request BOSUploadPartRequest* uploadPartRequest = [[BOSUploadPartRequest alloc] init]; uploadPartRequest.bucket = @"<bucketname>"; uploadPartRequest.key = @"<objectname>"; uploadPartRequest.objectData.data = data; uploadPartRequest.partNumber = i + 1; uploadPartRequest.uploadId = uploadID; __block BOSUploadPartResponse* uploadPartResponse = nil; task = [client uploadPart:uploadPartRequest]; task.then(^(BCEOutput* output) { if (output.response) { uploadPartResponse = (BOSUploadPartResponse*)output.response; BOSPart* part = [[BOSPart alloc] init]; part.partNumber = i + 1; part.eTag = uploadPartResponse.eTag; [parts addObject:part]; } }); [task waitUtilFinished]; }
注意:上面代码的核心是调用
uploadPart
方法来上传每一个分块,但是要注意以下几点:- uploadPart方法要求除最后一个Part以外,其他的Part大小都要大于等于5MB。但是Upload Part接口并不会立即校验上传Part的大小;只有当Complete Multipart Upload的时候才会校验。
- 为了保证数据在网络传输过程中不出现错误,建议您在
uploadPart
后,使用每个分块BOS返回的Content-MD5值分别验证已上传分块数据的正确性。当所有分块数据合成一个Object后,不再含MD5值。 - Part号码的范围是1~10000。如果超出这个范围,BOS将返回InvalidArgument的错误码。
- 每次上传Part时都要把流定位到此次上传块开头所对应的位置。
- 每次上传Part之后,BOS的返回结果会包含一个
BOSPart
对象,它是上传块的ETag与块编号(PartNumber)的组合,在后续完成分块上传的步骤中会用到它,因此需要将其保存起来。一般来讲这些BOSPart
对象将被保存到数组中。
完成分块上传
-
示例代码
BOSCompleteMultipartUploadRequest* compMultipartRequest = [[BOSCompleteMultipartUploadRequest alloc] init]; compMultipartRequest.bucket = @"<bucketname>"; compMultipartRequest.key = @"<objectname>"; compMultipartRequest.uploadId = uploadID; compMultipartRequest.parts = parts; __block BOSCompleteMultipartUploadResponse* complResponse = nil; task = [client completeMultipartUpload:compMultipartRequest]; task.then(^(BCEOutput* output) { if (output.response) { complResponse = (BOSCompleteMultipartUploadResponse*)output.response; NSLog(@"complte multiparts success!"); } if (output.error) { NSLog(@"complte multiparts failure %@", output.error); } }); [task waitUtilFinished];
说明:上面代码中的
parts
是第二步中保存的parts的列表,BOS收到用户提交的Part列表后,会逐一验证每个数据Part的有效性。当所有的数据Part验证通过后,BOS将把这些数据part组合成一个完整的Object。 -
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; // 初始化分块上传 BOSInitiateMultipartUploadRequest* initMPRequest = [[BOSInitiateMultipartUploadRequest alloc] init]; initMPRequest.bucket = @"<bucketname>"; initMPRequest.key = @"<objectname>"; initMPRequest.contentType = @"<content type>"; __block BOSInitiateMultipartUploadResponse* initMPResponse = nil; BCETask* task = [client initiateMultipartUpload:initMPRequest]; task.then(^(BCEOutput* output) { if (output.response) { initMPResponse = (BOSInitiateMultipartUploadResponse*)output.response; NSLog(@"initiate multipart upload success!"); } if (output.error) { NSLog(@"initiate multipart upload failure"); } }); [task waitUtilFinished]; NSString* uploadID = initMPResponse.uploadId; // 计算分块个数 NSString* file = @"/path/to/file.zip"; NSDictionary<NSString*, id>* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil]; uint64_t fileSize = attr.fileSize; uint64_t partSize = 1024 * 1024 * 5L; uint64_t partCount = fileSize / partSize; if (fileSize % partSize != 0) { ++partCount; } NSMutableArray<BOSPart*>* parts = [NSMutableArray array]; NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file.zip"]; for (uint64_t i = 0; i < partCount; ++i) { // seek uint64_t skip = partSize * i; [handle seekToFileOffset:skip]; uint64_t size = (partSize < fileSize - skip) ? partSize : fileSize - skip; // data NSData* data = [handle readDataOfLength:size]; // request BOSUploadPartRequest* uploadPartRequest = [[BOSUploadPartRequest alloc] init]; uploadPartRequest.bucket = @"<bucketname>"; uploadPartRequest.key = @"<objectname>"; uploadPartRequest.objectData.data = data; uploadPartRequest.partNumber = i + 1; uploadPartRequest.uploadId = uploadID; __block BOSUploadPartResponse* uploadPartResponse = nil; task = [client uploadPart:uploadPartRequest]; task.then(^(BCEOutput* output) { if (output.response) { uploadPartResponse = (BOSUploadPartResponse*)output.response; BOSPart* part = [[BOSPart alloc] init]; part.partNumber = i + 1; part.eTag = uploadPartResponse.eTag; [parts addObject:part]; } }); [task waitUtilFinished]; } BOSCompleteMultipartUploadRequest* compMultipartRequest = [[BOSCompleteMultipartUploadRequest alloc] init]; compMultipartRequest.bucket = @"<bucketname>"; compMultipartRequest.key = @"<objectname>"; compMultipartRequest.uploadId = uploadID; compMultipartRequest.parts = parts; __block BOSCompleteMultipartUploadResponse* complResponse = nil; task = [client completeMultipartUpload:compMultipartRequest]; task.then(^(BCEOutput* output) { if (output.response) { complResponse = (BOSCompleteMultipartUploadResponse*)output.response; NSLog(@"complte multiparts success!"); } if (output.error) { NSLog(@"complte multiparts failure %@", output.error); } }); [task waitUtilFinished]; }
取消分块上传
用户可以使用abortMultipartUpload方法取消分块上传。
-
示例代码
BOSAbortMultipartUploadRequest* abortRequest = [[BOSAbortMultipartUploadRequest alloc] init]; abortRequest.bucket = @"bucket"; abortRequest.key = @"<objectname>"; abortRequest.uploadId = uploadID; __block BOSAbortMultipartUploadResponse* abortResponse = nil; task = [client abortMultipartUpload:abortRequest]; task.then(^(BCEOutput* output) { if (output.response) { abortResponse = (BOSAbortMultipartUploadResponse*)output.response; NSLog(@"abort multiparts success!"); } if (output.error) { NSLog(@"abort multiparts failure %@", output.error); } }); [task waitUtilFinished];
获取未完成的分块上传
用户可以使用listMultipartUploads
方法获取Bucket内未完成的分块上传事件。
-
基本流程
- 创建BOSListMultipartUploadsRequest类的实例,传入
<BucketName>
参数。 - 创建BOSClient类的实例,执行BOSClient listMultipartUploads方法。
- listMultipartUploads返回所有未完成的分块上传信息。
- 创建BOSListMultipartUploadsRequest类的实例,传入
-
示例代码
BOSListMultipartUploadsRequest* listMultipartRequest = [[BOSListMultipartUploadsRequest alloc] init]; listMultipartRequest.bucket = @"<bucketname>"; __block BOSListMultipartUploadsResponse* listMultipartResponse = nil; task = [client listMultipartUploads:listMultipartRequest]; task.then(^(BCEOutput* output) { if (output.response) { listMultipartResponse = (BOSListMultipartUploadsResponse*)output.response; NSLog(@"list multipart success"); } if (output.error) { NSLog(@"list multipart failure %@", output.error); } }); [task waitUtilFinished];
注意:
- 默认情况下,如果Bucket中的分块上传事件的数目大于1000,则只会返回1000个Object,并且返回结果中IsTruncated的值为True,同时返回nextKeyMarker作为下次读取的起点。
- 若想获取更多分块上传事件,可以使用keyMarker参数分次读取。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSListMultipartUploadsRequest* listMultipartRequest = [[BOSListMultipartUploadsRequest alloc] init]; listMultipartRequest.bucket = @"<bucketname>"; __block BOSListMultipartUploadsResponse* listMultipartResponse = nil; BCETask* task = [client listMultipartUploads:listMultipartRequest]; task.then(^(BCEOutput* output) { if (output.response) { listMultipartResponse = (BOSListMultipartUploadsResponse*)output.response; NSLog(@"list multipart success"); } if (output.error) { NSLog(@"list multipart failure %@", output.error); } }); [task waitUtilFinished]; for (BOSMultipartUpload* upload in listMultipartResponse.uploads) { NSLog(@"upload id : %@", upload.uploadId); } }
获取所有已上传的分块信息
用户可以使用listParts
方法获取某个上传事件中所有已上传的块。
-
基本流程
- 创建BOSListPartsRequest类的实例,传入
<BucketName>
,<ObjectKey>
,<UploadId>
参数。 - 创建BOSClient类的实例,执行BOSClient listParts方法。
- listParts返回所有已上传part的信息。
- 创建BOSListPartsRequest类的实例,传入
-
示例代码
BOSListPartsRequest* listPartsRequest = [[BOSListPartsRequest alloc] init]; listPartsRequest.bucket = @"<bucketname>"; listPartsRequest.key = @"<objectname>"; listPartsRequest.uploadId = @"<upload id>";; __block BOSListPartsResponse* listPartsResponse = nil; BCETask* task = [client listParts:listPartsRequest]; task.then(^(BCEOutput* output) { if (output.response) { listPartsResponse = (BOSListPartsResponse*)output.response; NSLog(@"list parts success!"); } if (output.error) { NSLog(@"list part failure %@", output.error); } }); [task waitUtilFinished]; for (BOSPart* part in listPartsResponse.parts) { NSLog(@"part etag %@", part.eTag); }
注意:
- 默认情况下,如果Bucket中的分块上传事件的数目大于1000,则只会返回1000个Object,并且返回结果中IsTruncated的值为True,同时返回NextPartNumberMarker作为下次读取的起点。
- 若想获取更多已上传的分块信息,可以使用PartNumberMarker参数分次读取。
-
完整示例
#import <BaiduBCEBasic/BaiduBCEBasic.h> #import <BaiduBCEBOS/BaiduBCEBOS.h> void example(void) { // 初始化 BCECredentials* credentials = [[BCECredentials alloc] init]; credentials.accessKey = @"<access key>"; credentials.secretKey = @"<secret key>"; BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; configuration.credentials = credentials; BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; BOSListPartsRequest* listPartsRequest = [[BOSListPartsRequest alloc] init]; listPartsRequest.bucket = @"<bucketname>"; listPartsRequest.key = @"<objectname>"; listPartsRequest.uploadId = @"<upload id>";; __block BOSListPartsResponse* listPartsResponse = nil; BCETask* task = [client listParts:listPartsRequest]; task.then(^(BCEOutput* output) { if (output.response) { listPartsResponse = (BOSListPartsResponse*)output.response; NSLog(@"list parts success!"); } if (output.error) { NSLog(@"list part failure %@", output.error); } }); [task waitUtilFinished]; for (BOSPart* part in listPartsResponse.parts) { NSLog(@"part etag %@", part.eTag); } }