public void StreamChunkVerification() { var inputStr = "aaaaaaaaaa"; var sourceStream = GenerateStreamFromString(inputStr); var chunkCreator = new StreamChunkCreator(sourceStream, 2); var builder = new StringBuilder(); var i = 0; foreach (var stream in chunkCreator) { builder.Append(GetStringFromStream(stream)); i++; } Assert.True(inputStr.Equals(builder.ToString())); Assert.Equal(inputStr.Length / 2, i); }
private async Task <UploadResponse> MultipartUpload(UploadRequest uploadRequest, bool isNewUpload = true) { MultipartManifest manifest = null; var putobjectRequest = uploadRequest.PutObjectRequest; var chunkCreator = new StreamChunkCreator(putobjectRequest.PutObjectBody, _configuration.LengthPerUploadPartInMiB * MultipartUtils.MiB); // Uses single thread for multipart uploads. var executor = new SemaphoreSlim(_configuration.ParallelUploadCount); var assembler = new MultipartObjectAssembler(_osClient, putobjectRequest.NamespaceName, putobjectRequest.BucketName, putobjectRequest.ObjectName, uploadRequest.AllowOverwrite, executor, putobjectRequest.OpcClientRequestId, _configuration.EnforceMd5MultipartUpload, uploadRequest.RetryConfiguration); try { if (isNewUpload && !(uploadRequest is ResumeUploadRequest)) { var putObjectRequest = uploadRequest.PutObjectRequest; manifest = await assembler.NewRequest( putobjectRequest.ContentEncoding, putobjectRequest.ContentType, putobjectRequest.ContentLanguage, putobjectRequest.ContentDisposition, putobjectRequest.CacheControl, putobjectRequest.OpcMeta); } else { manifest = await assembler.ResumeUpload((uploadRequest as ResumeUploadRequest).UploadId).ConfigureAwait(false); } ProgressTracker progressTracker = null; if (uploadRequest.OnProgress != null) { progressTracker = new ProgressTracker(uploadRequest.OnProgress, putobjectRequest.PutObjectBody.Length); } int partNum = 1; foreach (var stream in chunkCreator) { if (!manifest.IsPartExists(partNum)) { logger.Info($"Creating Chunk: {partNum}"); if (progressTracker != null) { var progressStream = new ProgressTrackingInputStream(stream, progressTracker); await assembler.AddPart(progressStream, stream.Length, partNum).ConfigureAwait(false); } else { await assembler.AddPart(stream, stream.Length, partNum).ConfigureAwait(false); } } else { if (progressTracker != null) { progressTracker.OnRead(stream.Length); } logger.Info($"Skipping Part {partNum}"); } partNum++; } var response = await assembler.Commit().ConfigureAwait(false); logger.Info("Upload Complete"); return(new UploadResponse() { ETag = response.ETag, OpcClientRequestId = response.OpcClientRequestId, OpcRequestId = response.OpcRequestId, OpcMultipartMd5 = response.OpcMultipartMd5 }); } catch (Exception e) { if (manifest != null) { logger.Error($"Failed to upload object using multi-part uploads. Failed part numbers = '{string.Join(" ", manifest.ListFailedParts())}'" + $". Successful parts = '{string.Join(" ", manifest.ListCompletedParts())}', Upload Id = '{manifest.UploadId}'"); } if (_configuration.DisableAutoAbort) { logger.Info($"Not aborting failed multipart upload {manifest.UploadId} per configuration, client must manually abort it"); } else { logger.Info("Aborting in-progress uploads"); await assembler.Abort(); } throw e; } finally { executor.Dispose(); } }