异步Amazon S3多部分上传的进度信息和PartNumber。

3
我正在尝试使用多部分上传将文件上传到Amazon S3,使用此示例。我已将List<UploadPartRequest>更改为List<Task<UploadPartRequest>>,然后在其满时调用Task.WaitAll(myList.ToArray)

唯一的问题是,当我向每个UploadPartRequest对象添加进度事件时,我无法确定哪个部分会给我反馈信息(因为它们同时反馈!)。我可以同步地进行上传并跟踪当前上传的PartNumber,但这不是理想的,因为它明显要慢得多。

有人知道我如何在异步上传期间获取UploadPartRequestPartNumber吗?老实说,看起来确实没有什么方法(StreamTransferProgressArgs没有信息,似乎是唯一的方法),但我想试试看...

更新

这是我的代码片段:

private void MultiPartUpload(string localUNC, string destinationUNC)
{
    var uploadResponses = new List<UploadPartResponse>();
    var initiateRequest = new InitiateMultipartUploadRequest
    {
        BucketName = _bucket,
        Key = destinationUNC
    };

    var response = _s3.InitiateMultipartUpload(initiateRequest);
    var contentLength = new FileInfo(localUNC).Length;

    try
    {
        long filePosition = 0;
        for (TotalParts = 1; filePosition < contentLength; )
        {
            TotalParts++;
            filePosition += PartSize;
        }

        filePosition = 0;
        for (CurrentPart = 1; filePosition < contentLength; )
        {
            var uploadRequest = new UploadPartRequest()
            {
                BucketName = _bucket,
                Key = destinationUNC,
                UploadId = response.UploadId,
                PartNumber = CurrentPart,
                PartSize = PartSize,
                FilePosition = filePosition,
                FilePath = localUNC
            };

            uploadRequest.StreamTransferProgress += 
                new EventHandler<StreamTransferProgressArgs>(OnPartUploadProgressUpdate);
            uploadResponses.Add(_s3.UploadPart(uploadRequest));
            filePosition += PartSize;
            CurrentPart++;
        }

        var completeRequest = new CompleteMultipartUploadRequest()
        {
            BucketName = _bucket,
            Key = destinationUNC,
            UploadId = response.UploadId
        };

        var completeResponse = _s3.CompleteMultipartUpload(completeRequest);
    }
    catch (Exception e)
    {
        Console.WriteLine("Error during multi-part upload: {0}", e.Message);

        var abort = new AbortMultipartUploadRequest()
        {
            BucketName = _bucket,
            Key = destinationUNC,
            UploadId = response.UploadId
        };

        _s3.AbortMultipartUpload(abort);
    }
}

委托函数为:

    private static void OnPartUploadProgressUpdate(object sender, StreamTransferProgressArgs e)
    {
        //var obj = sender as AmazonS3Client;

        //if (obj != null)
        //{
            Console.WriteLine(
            "Part: {0} of {1} - {2:0.00}/{3:0.00}MB uploaded. {4}% complete.",
            CurrentPart,
            TotalParts,
            ConvertByte.ToMegabyte(e.TransferredBytes),
            ConvertByte.ToMegabyte(e.TotalBytes),
            e.PercentDone);
        //}
        //else
        //{
        //    Console.WriteLine(
        //        "{0}/{1}MB uploaded. {2}% complete.",
        //        ConvertByte.ToMegabyte(e.TransferredBytes),
        //        ConvertByte.ToMegabyte(e.TotalBytes),
        //        e.PercentDone);
        //}
    }
ConvertByte类是我自己创建的。我已经将注释掉的代码留下,这样您就可以看到我尝试过的内容。

事件处理程序的 sender 参数不是它所属的 UploadPartRequest 吗?尝试将其强制转换并访问其 PartNumber - svick
不,那个对象是AmazonS3Client对象,它(我认为)在识别正在上传的哪个部分方面是无用的。这非常令人沮丧,真的感觉要么我错过了一些简单的东西,要么亚马逊搞砸了一些简单的东西... - Chris Paton
在这种情况下,我认为最好的解决方案是使用lambda表达式。如果您发布您的代码(我不太明白您如何修改该示例),我可以向您展示我的意思。 - svick
@svick:完成了。谢谢! - Chris Paton
1个回答

1
你可以将事件处理程序设置为lambda表达式,这样它就可以访问uploadRequest本地变量:
uploadRequest.StreamTransferProgress +=
    (_, e) => OnPartUploadProgressUpdate(uploadRequest, e);

…

static void OnPartUploadProgressUpdate(
    UploadPartRequest request, StreamTransferProgressArgs e)
{
    var partNumber = request.PartNumber;
    …
}

那个很有效!虽然感到有点沮丧,没想到那个方法,但是没关系。人总是要不断学习的! - Chris Paton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接