更新时间:2026-04-28 GMT+08:00
分享

列举并行文件系统内文件(C SDK)

开发过程中,您有任何问题可以在github上提交issue,或者在华为云对象存储服务论坛中发帖求助。

您可以通过函数list_bucket_objects列举出并行文件系统里的文件。

接口约束

  • 每次接口调用最多返回1000个文件信息。
  • 您必须是并行文件系统拥有者或拥有列举并行文件系统内文件的权限,才能调用该接口。建议使用IAM或桶策略进行授权,如果使用IAM则需授予obs:bucket:ListBucket权限,如果使用桶策略则需授予ListBucket权限。相关授权方式介绍可参见OBS权限控制概述,配置方式详见使用IAM自定义策略自定义创建桶策略
  • OBS支持的Region与Endpoint的对应关系,详细信息请参见地区与终端节点

方法定义

1
2
void list_bucket_objects(const obs_options *options, const char *prefix, const char *marker, 
            const char *delimiter, int maxkeys, obs_list_objects_handler *handler, void *callback_data);

请求参数描述

表1 请求参数列表

字段名

类型

约束

说明

options

const obs_options *

必选

请求桶的上下文,配置option(C SDK),通过obs_options设置AK、SK、endpoint、bucket、超时时间、临时鉴权

prefix

char *

可选

限定返回的对象名必须带有prefix前缀。

marker

char *

可选

列举对象的起始位置,返回的对象列表将是对象名按照字典序排序后该参数以后的所有对象。

delimiter

char *

可选

用于对对象名进行分组的字符。对于对象名中包含delimiter的对象,其对象名(如果请求中指定了prefix,则此处的对象名需要去掉prefix)中从首字符至第一个delimiter之间的字符串将作为一个分组并作为commonPrefix返回。

对于并行文件系统,不携带此参数时默认列举是递归列举此目录下所有内容,会列举子目录。在大数据场景下(目录层级深、目录下文件多)的列举,建议设置[delimiter="/"],只列举当前目录下的内容,不列举子目录,提高列举效率。

maxkeys

int

必选

列举对象的最大数目,取值范围为1~1000,当超出范围时,按照默认的1000进行处理。

handler

obs_list_objects_handler *

必选

回调结构体,结构体内所有成员都是回调函数的指针,用于设置处理接口响应数据的回调函数。您可以通过设置回调函数,把服务端的响应数据复制到您的自定义回调数据callback_data中。

callback_data

void *

可选

用户自定义回调数据。

代码示例

以下示例展示如何列举并行文件系统内的对象:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#include "eSDKOBS.h"
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
// 响应回调函数,可以在这个回调中把properties的内容记录到callback_data(用户自定义回调数据)中
obs_status response_properties_callback(const obs_response_properties *properties, void *callback_data);
void listobjects_complete_callback(obs_status status,
    const obs_error_details *error,
    void *callback_data);
typedef struct list_object_callback_data
{
    int is_truncated;
    char next_marker[1024];
    int keyCount;
    int allDetails;
    obs_status ret_status;
} list_object_callback_data; 
obs_status list_objects_callback(int is_truncated, const char *next_marker,
    int contents_count,
    const obs_list_objects_content *contents,
    int common_prefixes_count,
    const char **common_prefixes,
    void *callback_data);
int main()
{
    // 以下示例展示如何通过函数list_bucket_objects列举出桶里的对象。
    // 在程序入口调用obs_initialize方法来初始化网络、内存等全局资源。
    obs_initialize(OBS_INIT_ALL); 
    obs_options options;
    // 创建并初始化options,该参数包括访问域名(host_name)、访问密钥(access_key_id和acces_key_secret)、桶名(bucket_name)、桶存储类别(storage_class)等配置信息
    init_obs_options(&options);
    // host_name填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
    options.bucket_options.host_name = "obs.cn-north-4.myhuaweicloud.com";
    // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
    // 本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY。
    options.bucket_options.access_key = getenv("ACCESS_KEY_ID");
    options.bucket_options.secret_access_key = getenv("SECRET_ACCESS_KEY");
    // 填写Bucket名称,例如example-bucket-name。
    char * bucketName = "example-bucket-name";
    options.bucket_options.bucket_name = bucketName;
    // 设置响应回调函数
    obs_list_objects_handler list_bucket_objects_handler =
    {
        { &response_properties_callback, &listobjects_complete_callback },
        &list_objects_callback
    };
    // 用户自定义回调数据
    list_object_callback_data data;
    memset(&data, 0, sizeof(list_object_callback_data));
    data.allDetails = 1;
    const char* prefix = NULL;
    const char* marker = NULL;
    const char* delimiter = "/";
    int maxkeys = 1000;
    // 列举对象
    list_bucket_objects(&options, prefix, marker, delimiter, maxkeys, &list_bucket_objects_handler, &data);
    if (OBS_STATUS_OK == data.ret_status) {
        printf("list bucket objects successfully. \n");
    }
    else
    {
        printf("list bucket objects failed(%s).\n",
            obs_get_status_name(data.ret_status));
    }
    // 释放分配的全局资源
    obs_deinitialize();
}
// 响应回调函数,可以在这个回调中把properties的内容记录到callback_data(用户自定义回调数据)中
obs_status response_properties_callback(const obs_response_properties *properties, void *callback_data)
{
    if (properties == NULL)
    {
        printf("error! obs_response_properties is null!");
        if (callback_data != NULL)
        {
            obs_sever_callback_data *data = (obs_sever_callback_data *)callback_data;
            printf("server_callback buf is %s, len is %llu",
                data->buffer, data->buffer_len);
            return OBS_STATUS_OK;
        }
        else {
            printf("error! obs_sever_callback_data is null!");
            return OBS_STATUS_OK;
        }
    }
    // 打印响应信息
#define print_nonnull(name, field)                                 \
    do {                                                           \
        if (properties-> field) {                                  \
            printf("%s: %s\n", name, properties->field);          \
        }                                                          \
    } while (0)
    print_nonnull("request_id", request_id);
    print_nonnull("request_id2", request_id2);
    print_nonnull("content_type", content_type);
    if (properties->content_length) {
        printf("content_length: %llu\n", properties->content_length);
    }
    print_nonnull("server", server);
    print_nonnull("ETag", etag);
    print_nonnull("expiration", expiration);
    print_nonnull("website_redirect_location", website_redirect_location);
    print_nonnull("version_id", version_id);
    print_nonnull("allow_origin", allow_origin);
    print_nonnull("allow_headers", allow_headers);
    print_nonnull("max_age", max_age);
    print_nonnull("allow_methods", allow_methods);
    print_nonnull("expose_headers", expose_headers);
    print_nonnull("storage_class", storage_class);
    print_nonnull("server_side_encryption", server_side_encryption);
    print_nonnull("kms_key_id", kms_key_id);
    print_nonnull("customer_algorithm", customer_algorithm);
    print_nonnull("customer_key_md5", customer_key_md5);
    print_nonnull("bucket_location", bucket_location);
    print_nonnull("obs_version", obs_version);
    print_nonnull("restore", restore);
    print_nonnull("obs_object_type", obs_object_type);
    print_nonnull("obs_next_append_position", obs_next_append_position);
    print_nonnull("obs_head_epid", obs_head_epid);
    print_nonnull("reserved_indicator", reserved_indicator);
    int i;
    for (i = 0; i < properties->meta_data_count; i++) {
        printf("x-obs-meta-%s: %s\n", properties->meta_data[i].name,
            properties->meta_data[i].value);
    }
    return OBS_STATUS_OK;
}
void print_error_details(const obs_error_details *error) {
    if (error && error->message) {
        printf("Error Message: \n   %s\n", error->message);
    }
    if (error && error->resource) {
        printf("Error Resource: \n  %s\n", error->resource);
    }
    if (error && error->further_details) {
        printf("Error further_details: \n   %s\n", error->further_details);
    }
    if (error && error->extra_details_count) {
        int i;
        for (i = 0; i < error->extra_details_count; i++) {
            printf("Error Extra Detail(%d):\n   %s:%s\n", i, error->extra_details[i].name,
                error->extra_details[i].value);
        }
    }
    if (error && error->error_headers_count) {
        int i;
        for (i = 0; i < error->error_headers_count; i++) {
            const char *errorHeader = error->error_headers[i];
            printf("Error Headers(%d):\n    %s\n", i, errorHeader == NULL ? "NULL Header" : errorHeader);
        }
    }
}
void listobjects_complete_callback(obs_status status,
    const obs_error_details *error,
    void *callback_data)
{
    if (callback_data)
    {
        list_object_callback_data *data = (list_object_callback_data *)callback_data;
        data->ret_status = status;
    }
    else {
        printf("Callback_data is NULL");
    }
    print_error_details(error);
}
static void printListBucketHeader(int allDetails)
{
    printf("%-50s  %-20s  %-5s",
        "   Key",
        "   Last Modified", "Size");
    if (allDetails) {
        printf("  %-34s  %-64s  %-12s            %-12s",
            "   ETag",
            "   Owner ID",
            "Display Name",
            "StorageClass");
    }
    printf("\n");
    printf("--------------------------------------------------  "
        "--------------------  -----");
    if (allDetails) {
        printf("  ----------------------------------  "
            "-------------------------------------------------"
            "---------------  ------------            ------------");
    }
    printf("\n");
}
obs_status list_objects_callback(int is_truncated, const char *next_marker,
    int contents_count,
    const obs_list_objects_content *contents,
    int common_prefixes_count,
    const char **common_prefixes,
    void *callback_data)
{
    list_object_callback_data *data = (list_object_callback_data *)callback_data;
    data->is_truncated = is_truncated;
    if ((!next_marker || !next_marker[0]) && contents_count) {
        next_marker = contents[contents_count - 1].key;
    }
    if (next_marker) {
        snprintf(data->next_marker, sizeof(data->next_marker), "%s",
            next_marker);
    }
    else {
        data->next_marker[0] = 0;
    }
    if (contents_count && !data->keyCount) {
        printListBucketHeader(data->allDetails);
    }
    int i;
    for (i = 0; i < contents_count; i++) {
        const obs_list_objects_content *content = &(contents[i]);
        char timebuf[256] = { 0 };
        time_t t = (time_t)content->last_modified;
        strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ",
            gmtime(&t));
        char sizebuf[16] = { 0 };
        if (content->size < 100000) {
            sprintf_s(sizebuf, sizeof(sizebuf), "%5llu", (unsigned long long) content->size);
        }
        else if (content->size < (1024 * 1024)) {
            sprintf_s(sizebuf, sizeof(sizebuf), "%4lluK",
                ((unsigned long long) content->size) / 1024ULL);
        }
        else if (content->size < (10 * 1024 * 1024)) {
            float f = content->size;
            f /= (1024 * 1024);
            sprintf_s(sizebuf, sizeof(sizebuf), "%1.2fM", f);
        }
        else if (content->size < (1024 * 1024 * 1024)) {
            sprintf_s(sizebuf, sizeof(sizebuf), "%4lluM",
                ((unsigned long long) content->size) /
                (1024ULL * 1024ULL));
        }
        else {
            float f = (content->size / 1024);
            f /= (1024 * 1024);
            sprintf_s(sizebuf, sizeof(sizebuf), "%1.2fG", f);
        }
        printf("%-50s  %s  %s", content->key, timebuf, sizebuf);
        if (data->allDetails) {
            printf("  %-36s  %-64s  %-20s  %-16s  %-16s",
                content->etag,
                content->owner_id ? content->owner_id : "",
                content->owner_display_name ? content->owner_display_name : "",
                content->storage_class ? content->storage_class : "",
                content->type ? content->type : ""
            );
        }
        printf("\n");
    }
    data->keyCount += contents_count;
    for (i = 0; i < common_prefixes_count; i++) {
        printf("\nCommon Prefix: %s\n", common_prefixes[i]);
    }
    printf("contents_count:%d\n", contents_count);
    return OBS_STATUS_OK;
}

相关链接

  • 关于列举并行文件系统内文件的API说明,请参见API文档。
  • 更多列举并行文件系统内文件返回的错误码含义、问题原因及处理措施可参考OBS错误码

相关文档