public Task <HeadObjectResponse> HeadObjectAsync(string bucketName, string objectKey, Action <HeadObjectRequest>?config = null, CancellationToken token = default) { HeadObjectRequest req = new HeadObjectRequest(bucketName, objectKey); config?.Invoke(req); return(_objectOperations.HeadObjectAsync(req, token)); }
public static async IAsyncEnumerable <GetObjectResponse> MultipartDownloadAsync(this IObjectOperations operations, 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 HeadObjectRequest headReq = new HeadObjectRequest(bucketName, objectKey); headReq.PartNumber = 1; HeadObjectResponse headResp = await operations.HeadObjectAsync(headReq, token).ConfigureAwait(false); Queue <Task <GetObjectResponse> > queue = new Queue <Task <GetObjectResponse> >(); if (headResp.NumberOfParts == null) { GetObjectRequest getReq = new GetObjectRequest(bucketName, objectKey); config?.Invoke(getReq); GetObjectResponse getResp = await operations.GetObjectAsync(getReq, token).ConfigureAwait(false); if (!getResp.IsSuccess) { throw new Exception(); } 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(operations, 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); } } } }