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); } } } }
public static async Task <ContentReader> GetObjectContentAsync(this IObjectClient client, string bucketName, string objectKey, Action <GetObjectRequest> config = null, CancellationToken token = default) { Validator.RequireNotNull(client, nameof(client)); Validator.RequireNotNull(bucketName, nameof(bucketName)); Validator.RequireNotNull(objectKey, nameof(objectKey)); GetObjectResponse resp = await client.GetObjectAsync(bucketName, objectKey, config, token).ConfigureAwait(false); if (resp.IsSuccess) { return(resp.Content); } return(null); }
public Task <GetObjectResponse> GetObjectAsync(string bucketName, string objectKey, Action <GetObjectRequest>?config = null, CancellationToken token = default) { return(_objectClient.GetObjectAsync(bucketName, objectKey, config, token)); }