Example #1
0
    public async IAsyncEnumerable <GetObjectResponse> MultipartDownloadAsync(string bucketName, string objectKey, Stream output, int bufferSize = 16777216, int numParallelParts = 4, Action <GetObjectRequest>?config = null, [EnumeratorCancellation] CancellationToken token = default)
    {
        Validator.RequireNotNull(output, nameof(output));

        //Use a HEAD request on the object key to determine if the file was originally uploaded with multipart
        HeadObjectResponse headResp = await _objectClient.HeadObjectAsync(bucketName, objectKey, req => req.PartNumber = 1, token).ConfigureAwait(false);

        Queue <Task <GetObjectResponse> > queue = new Queue <Task <GetObjectResponse> >();

        if (headResp.NumberOfParts == null)
        {
            GetObjectResponse getResp = await _objectClient.GetObjectAsync(bucketName, objectKey, config, token).ConfigureAwait(false);

            if (!getResp.IsSuccess)
            {
                throw new S3RequestException(getResp);
            }

            await getResp.Content.CopyToAsync(output, 81920, token).ConfigureAwait(false);

            yield return(getResp);
        }
        else
        {
            int parts = headResp.NumberOfParts.Value;

            using (SemaphoreSlim semaphore = new SemaphoreSlim(numParallelParts))
                using (Mutex mutex = new Mutex())
                {
                    for (int i = 1; i <= parts; i++)
                    {
                        await semaphore.WaitAsync(token).ConfigureAwait(false);

                        if (token.IsCancellationRequested)
                        {
                            yield break;
                        }

                        queue.Enqueue(DownloadPartAsync(bucketName, objectKey, output, headResp.ContentLength, i, bufferSize, semaphore, mutex, config, token));
                    }

                    while (queue.TryDequeue(out Task <GetObjectResponse>?task))
                    {
                        if (token.IsCancellationRequested)
                        {
                            yield break;
                        }

                        GetObjectResponse response = await task !.ConfigureAwait(false);
                        yield return(response);
                    }
                }
        }
    }
Example #2
0
 public Task <HeadObjectResponse> HeadObjectAsync(string bucketName, string objectKey, Action <HeadObjectRequest>?config = null, CancellationToken token = default)
 {
     return(_objectClient.HeadObjectAsync(bucketName, objectKey, config, token));
 }