Skip to content

Commit

Permalink
[Feature][ufilesdk-dev#11] 支持拉列表
Browse files Browse the repository at this point in the history
  • Loading branch information
gan.wu committed Dec 3, 2024
1 parent 879a493 commit cf26f31
Show file tree
Hide file tree
Showing 11 changed files with 478 additions and 7 deletions.
5 changes: 4 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ add_executable(delete delete.c)
target_link_libraries(delete ${DEPEND_LIB})

add_executable(async_mput async_mput.c thpool.c)
target_link_libraries(async_mput ${DEPEND_LIB} pthread) #link pthread 库
target_link_libraries(async_mput ${DEPEND_LIB} pthread) #link pthread 库

add_executable(list list.c)
target_link_libraries(list ${DEPEND_LIB})
62 changes: 62 additions & 0 deletions examples/list.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "../lib/api.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

void help(char *program_name) {
printf("Usage: %s <bucket_name> [prefix=""]\n", program_name);
}

int main(int argc, char *argv[]){
if(argc < 2 || argc > 3){
help(argv[0]);
return 1;
}

const char *bucket_name = argv[1];
const char *prefix = "";
if (argc > 2) {
prefix = argv[2];
}

struct ufile_config cfg;
cfg.public_key = getenv("UFILE_PUBLIC_KEY");
cfg.private_key = getenv("UFILE_PRIVATE_KEY");
cfg.bucket_host = "api.ucloud.cn";
cfg.file_host = "cn-bj.ufileos.com";

struct ufile_error error;
error = ufile_sdk_initialize(cfg, 1);
if(UFILE_HAS_ERROR(error.code)){
ufile_sdk_cleanup();
printf("Initialize SDK failed: %s\n", error.message);
return 1;
}

int once_list_count = 5;
char *marker = "";
char is_truncated = 1;
struct ufile_list_result result;
memset(&result, 0, sizeof(result));
while (is_truncated) {
error = ufile_list(bucket_name, prefix, "", once_list_count, marker, &result);
if(UFILE_HAS_ERROR(error.code)){
printf("List failed, error message: %s\n", error.message);
return 1;
} else{
int i = 0;
for (i = 0; i < result.entry_num; i++) {
printf("key: %s, size: %ld, mime_type: %s, last_modified: %ld, create_time: %ld, etag: %s, storage_class: %s\n",
result.entries[i].filename, result.entries[i].size, result.entries[i].mime_type, result.entries[i].last_modified,
result.entries[i].create_time, result.entries[i].etag, result.entries[i].storage_class);
}
marker = result.next_marker;
is_truncated = result.is_truncated;
}
}

ufile_free_list_result(result);

ufile_sdk_cleanup();
}
26 changes: 26 additions & 0 deletions lib/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,32 @@ ufile_free_file_info(struct ufile_file_info info){
}
}

void
ufile_free_list_result(struct ufile_list_result list_result) {
int i;
for (i = 0; i < list_result.entry_num; i++) {
struct ufile_list_result_entry *entry = &(list_result.entries[i]);
if (entry->filename != NULL) {
free((void*)(entry->filename));
}
if (entry->mime_type != NULL) {
free((void*)(entry->mime_type));
}
if (entry->filename != NULL) {
free((void*)(entry->etag));
}
if (entry->storage_class != NULL) {
free((void*)(entry->storage_class));
}
}
if(list_result.next_marker != NULL){
free((void*)list_result.next_marker);
}
if (list_result.entries != NULL){
free((void*)list_result.entries);
}
}

struct ufile_error
ufile_load_config_from_json(const char* json_buf, struct ufile_config *cfg){
struct ufile_error error = NO_ERROR;
Expand Down
30 changes: 30 additions & 0 deletions lib/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ struct ufile_error{
#define UFILE_MULTIPLE_NOT_FINISH_ERROR_CODE -5
#define UFILE_BUCKET_REQ_ERROR_CODE -10
#define CURL_ERROR_CODE -20
#define NO_MEMORY_ERROR_CODE -30
#define UFILE_PARSE_JSON_ERROR_CODE -40

#define NO_ERROR {0, ""}
#define CURL_INIT_ERROR_MSG "init curl failed."

#define UFILE_HAS_ERROR(CODE) ((CODE) != 0 && (CODE)/100 != 2 )

#define UFILE_LIST_MAX_COUNT (1000)
//****************************************************************** end

//*********************************config
Expand Down Expand Up @@ -154,6 +158,32 @@ ufile_bucket_create(const char *bucket_name, const char* region, const char* buc
//bucket_name 为 bucket 名字
extern struct ufile_error
ufile_bucket_delete(const char *bucket_name);

struct ufile_list_result_entry {
char *filename; // 文件名称
char *mime_type; // 文件mimetype
char *etag; // 标识文件内容
long long size; // 文件大小
char *storage_class; // 文件存储类型
long long last_modified; //文件最后修改时间
long long create_time; // 文件创建时间
};

struct ufile_list_result {
struct ufile_list_result_entry *entries;
int entry_num;
char is_truncated;
char *next_marker;
};

//拉取指定前缀的对象列表
extern struct ufile_error
ufile_list(const char *bucket_name, const char *prefix, const char *delimiter, int count, const char *marker, struct ufile_list_result *result);

//清理list结果
extern void
ufile_free_list_result(struct ufile_list_result list_result);

#ifdef __cplusplus
}
#endif
Expand Down
29 changes: 29 additions & 0 deletions lib/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,35 @@ char * ufile_file_authorization(const char *public_key, const char *private_key,
return ufile_strconcat("UCloud ", public_key, ":", signature, NULL);
}

char * ufile_file_authorization_for_list(const char *public_key, const char *private_key,
const char *method, const char *bucket,
const char *key, const char *mime_type,
const char *date, const char *md5, const char *prefix,
const char *marker,
const char *count,
const char *delimiter) {
char *sig_data = ufile_strconcat(method,"\n",
md5, "\n",
mime_type, "\n",
date, "\n",
"/",bucket, "/", key,
"\nlistobjects",
"\ndelimiter:", delimiter,
"\nmarker:", marker,
"\nmax-keys:", count,
"\nprefix:", prefix,
NULL);
unsigned char HMAC_str[HMAC_LEN];
HMAC_SHA1(HMAC_str, (unsigned char*)private_key, strlen(private_key),
(unsigned char*)sig_data, strlen(sig_data));

char signature[20];
base64encode(signature, (const char*)HMAC_str, 20);

free(sig_data);
return ufile_strconcat("UCloud ", public_key, ":", signature, NULL);
}

char * ufile_download_authorization(
const char* private_key,
const char* bucket,
Expand Down
7 changes: 7 additions & 0 deletions lib/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ char * ufile_file_authorization(const char *public_key, const char *private_key,
const char *key, const char *mime_type,
const char *date, const char *md5);

char * ufile_file_authorization_for_list(const char *public_key, const char *private_key,
const char *method, const char *bucket,
const char *key, const char *mime_type,
const char *date, const char *md5, const char *prefix,
const char *marker,
const char *count,
const char *delimiter);

//文件下载签名,mime_type, date, md5 可以为空。
//如果你加入了 date 请在 http 的 header 里面加入 Date: md5 头
Expand Down
56 changes: 50 additions & 6 deletions lib/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ set_http_options(struct http_options *opt,
return error;
}

if(strlen(key) == 0){
error.code = UFILE_CONFIG_ERROR_CODE;
error.message = "key connot be empty";
return error;
}

opt->header = NULL;
char *buf;
if (strlen(mime_type) != 0){
Expand All @@ -67,6 +61,56 @@ set_http_options(struct http_options *opt,
return error;
}

struct ufile_error
set_http_options_for_list(struct http_options *opt,
const char *method,
const char *mime_type,
const char *bucket,
const char *key,
const char *prefix,
const char *marker,
int count,
const char *delimiter) {
struct ufile_error error = NO_ERROR;
struct ufile_config *cfg = _global_config;

if (cfg == NULL){
error.code = UFILE_CONFIG_ERROR_CODE;
error.message = "global configuration has not been initialization yet.";
return error;
}

if(strlen(bucket) == 0){
error.code = UFILE_CONFIG_ERROR_CODE;
error.message = "bucket connot be empty";
return error;
}

char count_str[20];
snprintf(count_str, sizeof(count_str), "%d", count);

opt->header = NULL;
char *buf;
if (strlen(mime_type) != 0){
buf = ufile_strconcat("Content-Type: ", mime_type, NULL);
opt->header = curl_slist_append(opt->header, buf);
free(buf);
}
opt->header = curl_slist_append(opt->header, "User-Agent: UFile CSDK/2.0.0");

char *auth = ufile_file_authorization_for_list(cfg->public_key,cfg->private_key,method, bucket,
key, mime_type, "", "", prefix, marker, count_str, delimiter);
buf = ufile_strconcat("Authorization: ", auth, NULL);
opt->header = curl_slist_append(opt->header, buf);
free(auth);
free(buf);

opt->method = ufile_strconcat(method, NULL);
opt->url = ufile_strconcat(bucket, ".", cfg->file_host, "/", key, "?listobjects&delimiter=", delimiter,
"&marker=", marker, "&max-keys=", count_str, "&prefix=", prefix, NULL);
return error;
}

void
set_curl_options(CURL *curl,
struct http_options *opt) {
Expand Down
11 changes: 11 additions & 0 deletions lib/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ set_http_options(struct http_options *opt,
const char *key,
const char *query);

struct ufile_error
set_http_options_for_list(struct http_options *opt,
const char *method,
const char *mime_type,
const char *bucket,
const char *key,
const char *prefix,
const char *marker,
int count,
const char *delimiter);

struct ufile_error
set_download_options(
CURL *curl,
Expand Down
37 changes: 37 additions & 0 deletions lib/json.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <string.h>
#include "json.h"

int JsonGetBool(cJSON *root, const char *key, char *value) {
cJSON *item = cJSON_GetObjectItemCaseSensitive(root, key);
if (!cJSON_IsBool(item)) {
return -1; // Error
}
*value = cJSON_IsTrue(item) ? 1 : 0;
return 0;
}

int JsonGetString(cJSON *root, const char *key, char **value) {
cJSON *item = cJSON_GetObjectItemCaseSensitive(root, key);
if (!cJSON_IsString(item)) {
return -1; // Error
}
*value = strdup(item->valuestring);
return 0;
}

int JsonGetArray(cJSON *root, const char *key, cJSON **array) {
*array = cJSON_GetObjectItemCaseSensitive(root, key);
if (!cJSON_IsArray(*array)) {
return -1; // Error
}
return 0;
}

int JsonGetInt64(cJSON *root, const char *key, long long *value) {
cJSON *item = cJSON_GetObjectItemCaseSensitive(root, key);
if (!cJSON_IsNumber(item)) {
return -1; // Error
}
*value = (long long)item->valuedouble;
return 0;
}
9 changes: 9 additions & 0 deletions lib/json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "cJSON.h"

int JsonGetBool(cJSON *root, const char *key, char *value);

int JsonGetString(cJSON *root, const char *key, char **value);

int JsonGetArray(cJSON *root, const char *key, cJSON **array);

int JsonGetInt64(cJSON *root, const char *key, long long *value);
Loading

0 comments on commit cf26f31

Please sign in to comment.