列举未完成的分段上传

分段上传可以将大文件分割成片段后上传,除了最后一个片段,每个片段的数据大小为5MB~5GB。本文介绍如何列举未完成的分段上传,即已经用S3_initiate_multipart初始化,但仍然在进行或者S3_complete_multipart_upload失败的分段上传。

接口定义:

void S3_list_multipart_uploads(S3BucketContext *bucketContext,
                               const char *prefix, const char *keymarker,
                               const char *uploadidmarker,
                               const char *encodingtype, const char *delimiter,
                               int maxuploads, S3RequestContext *requestContext,
                               int timeoutMs,
                               const S3ListMultipartUploadsHandler *handler,
                               void *callbackData);

参数:

参数名 类型 说明
bucketContext S3BucketContext * 包含bucket及相关的请求参数
prefix const char * 如果非NULL,则仅列出拥有以该参数为前缀的key的分段上传
keymarker const char * 如果非NULL,则和uploadidmarker一起指定了只有排序在其后的分段上传才会被列出
uploadidmarker const char * 如果非NULL,则和keymarker一起指定了只有排序在其后的分段上传才会被列出
encodingtype const char * 如果非NULL,则请求服务器以指定方法编码响应
delimiter const char * 如果非NULL,则用于对key进行分组
maxuploads int 设置返回的分段上传数的最大数量
requestContext S3RequestContext * 请求参数,如果为NULL,则立即同步执行请求
timeoutMs int 如果非0,则是以毫秒为单位的请求超时时间
handler const S3ListMultipartUploadsHandler * 回调函数
callbackData void * 回调数据

代码示例:

typedef struct list_multiparts_callback_data
{
    int isTruncated;
    char nextKeyMarker[1024];
    char nextUploadIdMarker[1024];
    int uploadCount;
    int allDetails;
} list_multiparts_callback_data;

static S3Status listMultipartCallback(int isTruncated, const char *nextKeyMarker,
                                      const char *nextUploadIdMarker,
                                      int uploadsCount,
                                      const S3ListMultipartUpload *uploads,
                                      int commonPrefixesCount,
                                      const char **commonPrefixes,
                                      void *callbackData)
{
    list_multiparts_callback_data *data =
        (list_multiparts_callback_data *)callbackData;

    data->isTruncated = isTruncated;
    if (nextKeyMarker)
    {
        snprintf(data->nextKeyMarker, sizeof(data->nextKeyMarker), "%s",
                 nextKeyMarker);
    }
    else
    {
        data->nextKeyMarker[0] = 0;
    }

    if (nextUploadIdMarker)
    {
        snprintf(data->nextUploadIdMarker, sizeof(data->nextUploadIdMarker), "%s",
                 nextUploadIdMarker);
    }
    else
    {
        data->nextUploadIdMarker[0] = 0;
    }

    if (uploadsCount && !data->uploadCount)
    {
        printListMultipartHeader(data->allDetails);
    }

    int i;
    for (i = 0; i < uploadsCount; i++)
    {
        const S3ListMultipartUpload *upload = &(uploads[i]);
        char timebuf[256];
        if (1)
        {
            time_t t = (time_t)upload->initiated;
            strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ",
                     gmtime(&t));
            printf("\nKey: %s\n", upload->key);
            printf("Initiated: %s\n", timebuf);
            printf("UploadId: %s\n", upload->uploadId);
            if (upload->initiatorId)
            {
                printf("Initiator ID: %s\n", upload->initiatorId);
            }
            if (upload->initiatorDisplayName)
            {
                printf("Initiator Display Name: %s\n", upload->initiatorDisplayName);
            }
            if (upload->ownerId)
            {
                printf("Owner ID: %s\n", upload->ownerId);
            }
            if (upload->ownerDisplayName)
            {
                printf("Owner Display Name: %s\n", upload->ownerDisplayName);
            }
            printf("StorageClass: %s\n", upload->storageClass);
        }
        else
        {
            time_t t = (time_t)upload->initiated;
            strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ",
                     gmtime(&t));
            printf("%-50s  %s %-50s", upload->key, timebuf, upload->uploadId);
            if (data->allDetails)
            {
                printf("  %-34s  %-64s  %-12s  %-64s  %-12s",
                       upload->storageClass,
                       upload->ownerId ? upload->ownerId : "",
                       upload->ownerDisplayName ? upload->ownerDisplayName : "",
                       upload->initiatorId ? upload->initiatorId : "",
                       upload->initiatorDisplayName ? upload->initiatorDisplayName : "");
            }
            printf("\n");
        }
    }

    data->uploadCount += uploadsCount;

    for (i = 0; i < commonPrefixesCount; i++)
    {
        printf("\nCommon Prefix: %s\n", commonPrefixes[i]);
    }

    return S3StatusOK;
}

void printListMultipartHeader(int allDetails)
{
    (void)allDetails;
}

void list_multipart_uploads(const char *prefix, const char *keymarker, const char *delimiter,
                            const char *encodingtype, const char *uploadidmarker, int maxuploads)
{
    int allDetails = 0;

    S3ListMultipartUploadsHandler listMultipartUploadsHandler =
        {
            {&responsePropertiesCallback, &responseCompleteCallback},
            &listMultipartCallback};

    list_multiparts_callback_data data;

    memset(&data, 0, sizeof(list_multiparts_callback_data));
    if (keymarker != 0)
    {
        snprintf(data.nextKeyMarker, sizeof(data.nextKeyMarker), "%s",
                 keymarker);
    }
    if (uploadidmarker != 0)
    {
        snprintf(data.nextUploadIdMarker, sizeof(data.nextUploadIdMarker),
                 "%s", uploadidmarker);
    }
    data.uploadCount = 0;
    data.allDetails = allDetails;

    do
    {
        data.isTruncated = 0;
        do
        {
            S3_list_multipart_uploads(&bucketContext, prefix,
                                      data.nextKeyMarker,
                                      data.nextUploadIdMarker, encodingtype,
                                      delimiter, maxuploads, 0,
                                      0,
                                      &listMultipartUploadsHandler, &data);
        } while (S3_status_is_retryable(statusG) && should_retry());
        if (statusG != S3StatusOK)
        {
            break;
        }
    } while (data.isTruncated &&
             (!maxuploads || (data.uploadCount < maxuploads)));

    if (statusG == S3StatusOK)
    {
        if (!data.uploadCount)
        {
            printListMultipartHeader(data.allDetails);
        }
    }
    else
    {
        printError();
    }
}