列举存储空间中的文件
列举存储空间中的文件
BOS SDK支持用户通过以下两种方式列举出object:
- 简单列举
- 通过参数复杂列举
除此之外,用户还可在列出文件的同时模拟文件夹
简单列举
当用户希望简单快速列举出所需的文件时,可通过listObjects方法返回ListObjectsResponse对象,ListObjectsResponse对象包含了此次listObject请求的返回结果。用户可以通过ListObjectsResponse中的getContents方法获取所有Object的描述信息。
1void listObjects(Client& client, const std::string bucketName) {
2    ListObjectsRequest listObjectsRequest(bucketName);
3    // 获取指定Bucket下的所有Object信息
4    ListObjectsResponse listObjectsResponse;
5    int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
6
7    if (ret != 0) return;
8    if (listObjectResponse.is_fail()) {
9        return;
10    }
11    // 遍历所有Object
12    for (const ObjectSummary& objectSummary : listObjectsResponse.contents()) {
13        std::cout << "ObjectKey: " << objectSummary.key << std::endl;
14    }
15}注意:
- 默认情况下,如果Bucket中的Object数量大于1000,则只会返回1000个Object,并且返回结果中is_truncated值为True,并返回next_marker做为下次读取的起点。
- 若想增大返回Object的数目,可以使用marker参数分次读取。
通过参数复杂列举
除上述简单列举外,用户还可通过设置ListObjectsRequest的参数实现各种灵活的查询功能。ListObjectsRequest的可设置的参数如下:
| 参数 | 功能 | 使用方式 | 
|---|---|---|
| prefix | 限定返回的object key必须以prefix作为前缀 | set_prefix(const std::string& prefix) | 
| delimiter | 是一个用于对Object名字进行分组的字符所有名字包含指定的前缀且第一次出现。Delimiter字符之间的object作为一组元素: CommonPrefixes | set_delimiter(const std::string& delimiter) | 
| marker | 设定结果从marker之后按字母排序的第一个开始返回 | set_marker(const std::string& marker) | 
| max_keys | 限定此次返回object的最大数,最大为1000,默认值是1000。如果指定的值大于1000,按1000操作 | set_max_keys(int maxKeys) | 
注意:
- 如果有Object以Prefix命名,当仅使用Prefix查询时,返回的所有Key中仍会包含以Prefix命名的Object,详见递归列出目录下所有文件。
- 如果有Object以Prefix命名,当使用Prefix和Delimiter组合查询时,返回的所有Key中会有Null,Key的名字不包含Prefix前缀,详见查看目录下的文件和子目录。
下面我们分别以几个案例说明通过参数列举的方法:
指定最大返回条数
1// 指定最大返回条数为500
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_max_keys(500);
4ListObjectsResponse listObjectsResponse;
5int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
6if (ret != 0) return;
7...//response异常处理
8for(const ObjectSummary& objectSummary :listObjectsResponse.contents()) {
9    std::cout << "ObjectKey: " << objectSummary.key << std::endl;
10}返回指定前缀的object
1// 指定返回前缀为test的object
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_prefix("test");
4ListObjectsResponse listObjectsResponse;
5int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
6if (ret != 0) return;
7...//response异常处理
8for(const ObjectSummary& objectSummary :listObjectsResponse.contents()) {
9    std::cout << "ObjectKey: " << objectSummary.key << std::endl;
10}从指定Object后返回
1// 用户可以定义不包括某object,从其之后开始返回
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_marker("object");
4ListObjectsResponse listObjectsResponse;
5int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
6if (ret != 0) return;
7...//response异常处理
8for(const ObjectSummary& objectSummary :listObjectsResponse.contents()) {
9    std::cout << "ObjectKey: " << objectSummary.key << std::endl;
10}分页获取所有Object
1// 用户可设置每页最多500条记录
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_max_keys(500);
4ListObjectsResponse listObjectsResponse;
5int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
6if (ret != 0) return;
7...//response异常处理
8
9bool isTruncated = true;
10while (isTruncated) {
11    ListObjectsResponse listObjectsResponse;
12    client.list_objects(listObjectsRequest, &listObjectsResponse);
13    isTruncated = listObjectsResponse.is_truncated();
14    if (listObjectsResponse.next_marker() != "") {
15        listObjectsRequest.set_marker(listObjectsResponse.next_marker());
16    }
17}分页获取所有特定Object后的结果
1// 用户可设置每页最多500条记录,并从某特定object之后开始获取
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_max_keys(500);
4listObjectsRequest.set_marker("object");
5ListObjectsResponse listObjectsResponse;
6int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
7if (ret != 0) return;
8
9bool isTruncated = true;
10while (isTruncated) {
11    ListObjectsResponse listObjectsResponse;
12    client.list_objects(listObjectsRequest, &listObjectsResponse);
13    isTruncated = listObjectsResponse.is_truncated();
14    if (listObjectsResponse.next_marker() != "") {
15        listObjectsRequest.set_marker(listObjectsResponse.next_marker());
16    }
17}分页获取所有指定前缀的Object结果
1// 用户可设置分页获取指定前缀的Object,每页最多500条记录
2ListObjectsRequest listObjectsRequest("bucketName");
3listObjectsRequest.set_max_keys(500);
4listObjectsRequest.set_prefix("object");
5ListObjectsResponse listObjectsResponse;
6int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
7if (ret != 0) return;
8
9bool isTruncated = true;
10while (isTruncated) {
11    ListObjectsResponse listObjectsResponse;
12    client.list_objects(listObjectsRequest, &listObjectsResponse);
13    isTruncated = listObjectsResponse.is_truncated();
14    if (listObjectsResponse.next_marker() != "") {
15        listObjectsRequest.set_marker(listObjectsResponse.next_marker());
16    }
17}list_object方法返回的ListObjectsResponse解析类中可供调用的参数有:  
| 参数 | 说明 | 
|---|---|
| name | Bucket名称 | 
| prefix | 匹配以prefix开始到第一次出现Delimiter字符之间的object作为一组元素返回 | 
| marker | 本次查询的起点 | 
| max_keys | 请求返回的最大数目 | 
| is_truncated | 指明是否所有查询都返回了;false-本次已经返回所有结果,true-本次还没有返回所有结果 | 
| contents | 返回的一个Object的容器 | 
| +key | Object名称 | 
| +last_modified | 此Object最后一次被修改的时间 | 
| +etag | Object的HTTP协议实体便签 | 
| +storage_class | Object的存储形态 | 
| +size | Object的内容的大小(字节数) | 
| +owner_id | Bucket Owner的用户ID | 
| +owner_display_name | Bucket Owner的名称 | 
模拟文件夹功能
在BOS的存储结果中是没有文件夹这个概念的,所有元素都是以Object来存储,但BOS的用户在使用数据时往往需要以文件夹来管理文件。 因此,BOS提供了创建模拟文件夹的能力,其本质上来说是创建了一个size为0的Object。对于这个Object可以上传下载,只是控制台会对以”/“结尾的Object以文件夹的方式展示。
用户可以通过 Delimiter 和 Prefix 参数的配合模拟出文件夹功能。Delimiter 和 Prefix 的组合效果是这样的:
如果把 Prefix 设为某个文件夹名,就可以罗列以此 Prefix 开头的文件,即该文件夹下递归的所有的文件和子文件夹(目录)。文件名在Contents中显示。 如果再把 Delimiter 设置为 “/” 时,返回值就只罗列该文件夹下的文件和子文件夹(目录),该文件夹下的子文件名(目录)返回在 CommonPrefixes 部分,子文件夹下递归的文件和文件夹不被显示。
如下是几个应用方式:
列出Bucket内所有文件
当用户需要获取Bucket下的所有文件时,可以参考分页获取所有Object
递归列出目录下所有文件
可以通过设置 Prefix 参数来获取某个目录下所有的文件:
1// 构造ListObjectsRequest请求
2ListObjectsRequest listObjectsRequest("bucketName");
3// 递归列出fun目录下的所有文件
4listObjectsRequest.set_prefix("fun/");
5ListObjectsResponse listObjectsResponse;
6int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
7if (ret != 0) return;
8...//response异常处理
9std::cout << "ObjectKeys:" << std::endl;
10// 遍历所有Object
11for(const ObjectSummary& objectSummary :listObjectsResponse.contents()) {
12    std::cout << objectSummary.key << std::endl;
13}输出:
1ObjectKeys:
2fun/
3fun/movie/001.avi
4fun/movie/007.avi
5fun/test.jpg查看目录下的文件和子目录
在 Prefix 和 Delimiter 结合的情况下,可以列出目录下的文件和子目录:
1// 构造ListObjectsRequest请求
2ListObjectsRequest listObjectsRequest("bucketName");
3
4// "/" 为文件夹的分隔符
5listObjectsRequest.set_delimiter("/");
6
7// 列出fun目录下的所有文件和文件夹
8listObjectsRequest.set_prefix("fun/");
9
10ListObjectsResponse listObjectsResponse;
11int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
12if (ret != 0) return;   
13// 遍历所有Object
14std::cout << "\nObjectKeys:" << std::endl;
15for(const ObjectSummary& objectSummary :listObjectsResponse.contents()) {
16    std::cout << objectSummary.key << std::endl;
17}
18    
19// 遍历所有CommonPrefix
20std::cout << "CommonPrefixs:" << std::endl;
21for (const std::string& commonPrefix : listObjectsResponse.common_prefixes()) {
22    std::cout << commonPrefix << std::endl;
23}输出:
1ObjectKeys:
2fun/
3fun/test.jpg
4
5CommonPrefixs:
6fun/movie/返回的结果中, ObjectSummary 的列表contents中给出的是fun目录下的文件。而 common_prefixes 的列表中给出的是fun目录下的所有子文件夹。可以看出 fun/movie/001.avi , fun/movie/007.avi 两个文件并没有被列出来,因为它们属于 fun 文件夹下的 movie 目录。
列举Bucket中object的存储属性
当用户完成上传后,如果需要查看指定Bucket中的全部Object的storage class属性,可以通过如下代码实现:
1public void listObjectsStorageClass(){
2    ListObjectsRequest listObjectsRequest("bucketName");
3    ListObjectsResponse listObjectsResponse;
4    int ret = client.list_objects(listObjectsRequest, &listObjectsResponse);
5    std::vector<ObjectSummary> objectList = listObjectResponse.contents();
6    for(int i = 0; i<objectList.size(); i++) {
7        std::cout << objectList[i].storage_class() << std::endl;
8    }
9}