列举已上传的片段
分段上传可以将大文件分割成片段后上传,除了最后一个片段,每个片段的数据大小为5MB~5GB。本文介绍如何列举已上传的片段部分。
接口定义:
void S3_list_parts(S3BucketContext *bucketContext, const char *key,
const char *partnumbermarker,
const char *uploadid, const char *encodingtype,
int maxparts, S3RequestContext *requestContext,
int timeoutMs,
const S3ListPartsHandler *handler, void *callbackData);
参数:
参数名 | 类型 | 说明 |
---|---|---|
bucketContext | S3BucketContext * | 包含bucket及相关的请求参数 |
key | const char * | 将要上传的对象的文件名 |
partnumbermarker | const char * | 如果非NULL,则仅列出partnumber比该参数高的part |
upload_id | const char * | S3_initiate_multipart中得到的upload_id |
encodingtype | const char * | 如果非NULL,则请求服务器以指定方法编码响应 |
maxparts | int | 指定返回响应体中part的最大数量 |
requestContext | S3RequestContext * | 请求参数,如果为NULL,则立即同步执行请求 |
timeoutMs | int | 如果非0,则是以毫秒为单位的请求超时时间 |
handler | const S3ListPartsHandler * | 回调函数 |
callbackData | void * | 回调数据 |
示例代码:
typedef struct growbuffer
{
// The total number of bytes, and the start byte
int size;
// The start byte
int start;
// The blocks
char data[64 * 1024];
struct growbuffer *prev, *next;
} growbuffer;
typedef struct UploadManager
{
//used for initial multipart
char *upload_id;
//used for upload part object
char **etags;
int next_etags_pos;
//used for commit Upload
growbuffer *gb;
int remaining;
} UploadManager;
typedef struct list_parts_callback_data
{
int isTruncated;
char nextPartNumberMarker[24];
char initiatorId[256];
char initiatorDisplayName[256];
char ownerId[256];
char ownerDisplayName[256];
char storageClass[256];
int partsCount;
int handlePartsStart;
int allDetails;
int noPrint;
UploadManager *manager;
} list_parts_callback_data;
void printListMultipartHeader(int allDetails)
{
(void)allDetails;
}
void printListPartsHeader()
{
printf("%-25s %-30s %-30s %-15s",
"LastModified",
"PartNumber", "ETag", "SIZE");
printf("\n");
printf("--------------------- "
" ------------- "
"------------------------------- "
" -----");
printf("\n");
}
S3Status listPartsCallback(int isTruncated,
const char *nextPartNumberMarker,
const char *initiatorId,
const char *initiatorDisplayName,
const char *ownerId,
const char *ownerDisplayName,
const char *storageClass,
int partsCount,
int handlePartsStart,
const S3ListPart *parts,
void *callbackData)
{
list_parts_callback_data *data =
(list_parts_callback_data *)callbackData;
data->isTruncated = isTruncated;
data->handlePartsStart = handlePartsStart;
UploadManager *manager = data->manager;
if (nextPartNumberMarker)
{
snprintf(data->nextPartNumberMarker,
sizeof(data->nextPartNumberMarker), "%s",
nextPartNumberMarker);
}
else
{
data->nextPartNumberMarker[0] = 0;
}
if (initiatorId)
{
snprintf(data->initiatorId, sizeof(data->initiatorId), "%s",
initiatorId);
}
else
{
data->initiatorId[0] = 0;
}
if (initiatorDisplayName)
{
snprintf(data->initiatorDisplayName,
sizeof(data->initiatorDisplayName), "%s",
initiatorDisplayName);
}
else
{
data->initiatorDisplayName[0] = 0;
}
if (ownerId)
{
snprintf(data->ownerId, sizeof(data->ownerId), "%s",
ownerId);
}
else
{
data->ownerId[0] = 0;
}
if (ownerDisplayName)
{
snprintf(data->ownerDisplayName, sizeof(data->ownerDisplayName), "%s",
ownerDisplayName);
}
else
{
data->ownerDisplayName[0] = 0;
}
if (storageClass)
{
snprintf(data->storageClass, sizeof(data->storageClass), "%s",
storageClass);
}
else
{
data->storageClass[0] = 0;
}
if (partsCount && !data->partsCount && !data->noPrint)
{
printListPartsHeader();
}
int i;
for (i = 0; i < partsCount; i++)
{
const S3ListPart *part = &(parts[i]);
char timebuf[256];
if (data->noPrint)
{
manager->etags[handlePartsStart + i] = strdup(part->eTag);
manager->next_etags_pos++;
manager->remaining = manager->remaining - part->size;
}
else
{
time_t t = (time_t)part->lastModified;
strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ",
gmtime(&t));
printf("%-30s", timebuf);
printf("%-15llu", (unsigned long long)part->partNumber);
printf("%-45s", part->eTag);
printf("%-15llu\n", (unsigned long long)part->size);
}
}
data->partsCount += partsCount;
return S3StatusOK;
}
void list_parts(const char *key,
const char *uploadid, const char *partnumbermarker,
const char *encodingtype, int maxparts)
{
int allDetails = 1;
S3ListPartsHandler listPartsHandler =
{
{&responsePropertiesCallback, &responseCompleteCallback},
&listPartsCallback};
list_parts_callback_data data;
memset(&data, 0, sizeof(list_parts_callback_data));
if (partnumbermarker != 0)
{
snprintf(data.nextPartNumberMarker,
sizeof(data.nextPartNumberMarker), "%s", partnumbermarker);
}
data.partsCount = 0;
data.allDetails = allDetails;
data.noPrint = 0;
do
{
data.isTruncated = 0;
do
{
S3_list_parts(&bucketContext, key, data.nextPartNumberMarker,
uploadid, encodingtype,
maxparts,
0, 0,
&listPartsHandler, &data);
} while (S3_status_is_retryable(statusG) && should_retry());
if (statusG != S3StatusOK)
{
break;
}
} while (data.isTruncated &&
(!maxparts || (data.partsCount < maxparts)));
if (statusG == S3StatusOK)
{
if (!data.partsCount)
{
printListMultipartHeader(data.allDetails);
}
}
else
{
printError();
}
}