public Task <CompleteMultipartUploadResponse> CompleteMultipartUploadAsync(string bucketName, string objectKey, string uploadId, IEnumerable <UploadPartResponse> parts, Action <CompleteMultipartUploadRequest>?config = null, CancellationToken token = default) { CompleteMultipartUploadRequest req = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, parts); config?.Invoke(req); return(_multipartOperations.CompleteMultipartUploadAsync(req, token)); }
public static async IAsyncEnumerable <UploadPartResponse> MultipartUploadAsync(this IMultipartOperations operations, CreateMultipartUploadRequest req, Stream data, int partSize = 16777216, int numParallelParts = 4, [EnumeratorCancellation] CancellationToken token = default) { Validator.RequireNotNull(req, nameof(req)); Validator.RequireNotNull(data, nameof(data)); foreach (IRequestWrapper wrapper in operations.RequestWrappers) { if (wrapper.IsSupported(req)) { data = wrapper.Wrap(data, req); } } string bucket = req.BucketName; string objectKey = req.ObjectKey; CreateMultipartUploadResponse initResp = await operations.CreateMultipartUploadAsync(req, token).ConfigureAwait(false); if (token.IsCancellationRequested) { yield break; } if (!initResp.IsSuccess) { throw new S3RequestException(initResp.StatusCode, "CreateMultipartUploadRequest was unsuccessful"); } Queue <Task <UploadPartResponse> > uploads = new Queue <Task <UploadPartResponse> >(); using (SemaphoreSlim semaphore = new SemaphoreSlim(numParallelParts)) { long offset = 0; for (int i = 1; offset < data.Length; i++) { await semaphore.WaitAsync(token).ConfigureAwait(false); if (token.IsCancellationRequested) { break; } byte[] partData = new byte[partSize]; int read = await data.ReadUpToAsync(partData, 0, partData.Length, token).ConfigureAwait(false); TaskCompletionSource <UploadPartResponse> completionSource = new TaskCompletionSource <UploadPartResponse>(); uploads.Enqueue(completionSource.Task); UploadPartAsync(completionSource, operations, bucket, objectKey, partData, read, i, initResp.UploadId, semaphore, token); offset += partSize; } Queue <UploadPartResponse> responses = new Queue <UploadPartResponse>(uploads.Count); while (uploads.TryDequeue(out Task <UploadPartResponse>?task)) { if (token.IsCancellationRequested) { yield break; } UploadPartResponse response = await task !.ConfigureAwait(false); responses.Enqueue(response); yield return(response); } CompleteMultipartUploadRequest completeReq = new CompleteMultipartUploadRequest(bucket, objectKey, initResp.UploadId, responses); CompleteMultipartUploadResponse completeResp = await operations.CompleteMultipartUploadAsync(completeReq, token).ConfigureAwait(false); if (!completeResp.IsSuccess) { throw new S3RequestException(completeResp.StatusCode, "CompleteMultipartUploadRequest was unsuccessful"); } } }