From 33bf1da208c983f21be30da49fc3d3475b2129e3 Mon Sep 17 00:00:00 2001 From: poorna Date: Mon, 18 Sep 2017 14:48:07 -0700 Subject: [PATCH] Fix PutObject call for unknown size stream --- Minio.Functional.Tests/FunctionalTest.cs | 32 ++++++++++++++++++++++++ Minio/ApiEndpoints/ObjectOperations.cs | 20 ++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Minio.Functional.Tests/FunctionalTest.cs b/Minio.Functional.Tests/FunctionalTest.cs index f9df4662d..67d713c48 100644 --- a/Minio.Functional.Tests/FunctionalTest.cs +++ b/Minio.Functional.Tests/FunctionalTest.cs @@ -167,6 +167,7 @@ public static void Main(string[] args) PutObject_Test5(minioClient).Wait(); PutObject_Test6(minioClient).Wait(); PutObject_Test7(minioClient).Wait(); + PutObject_Test8(minioClient).Wait(); // Test StatObject function StatObject_Test1(minioClient).Wait(); @@ -575,6 +576,37 @@ private async static Task PutObject_Test7(MinioClient minio) new MintLogger("PutObject_Test7","Tests thread safety of minioclient on a parallel put operation",TestStatus.FAIL,(DateTime.Now - startTime),"",ex.Message, ex.ToString()).Log(); } } + private async static Task PutObject_Test8(MinioClient minio) + { + DateTime startTime = DateTime.Now; + try { + // Putobject call with unknown stream size. See if PutObjectAsync call succeeds + string bucketName = GetRandomName(15); + string objectName = GetRandomName(10); + string contentType = "application/octet-stream"; + + await Setup_Test(minio, bucketName); + using (System.IO.MemoryStream filestream = rsg.GenerateStreamFromSeed(1 * MB)) + { + + long size = -1; + long file_write_size = filestream.Length; + + await minio.PutObjectAsync(bucketName, + objectName, + filestream, + size, + contentType); + await minio.RemoveObjectAsync(bucketName, objectName); + await TearDown(minio, bucketName); + } + new MintLogger("PutObject_Test8","Tests whether PutObject with unknown stream-size passes",TestStatus.PASS,(DateTime.Now - startTime)).Log(); + } + catch (Exception ex) + { + new MintLogger("PutObject_Test8","Tests whether PutObject with unknown stream-size passes",TestStatus.FAIL,(DateTime.Now - startTime),"",ex.Message, ex.ToString()).Log(); + } + } private async static Task PutObject_Task(MinioClient minio, string bucketName, string objectName, string fileName = null, string contentType = "application/octet-stream", long size = 0, Dictionary metaData = null, MemoryStream mstream = null) { try diff --git a/Minio/ApiEndpoints/ObjectOperations.cs b/Minio/ApiEndpoints/ObjectOperations.cs index 942437965..5efbf1487 100644 --- a/Minio/ApiEndpoints/ObjectOperations.cs +++ b/Minio/ApiEndpoints/ObjectOperations.cs @@ -248,11 +248,16 @@ await GetObjectAsync(bucketName, objectName, (stream) => double expectedReadSize = partSize; int partNumber; + int numPartsUploaded = 0; bool skipUpload = false; for (partNumber = 1; partNumber <= partCount; partNumber++) { byte[] dataToCopy = ReadFull(data, (int)partSize); - + if (dataToCopy == null) + { + break; + } + if (partNumber == partCount) { expectedReadSize = lastPartSize; @@ -278,22 +283,29 @@ await GetObjectAsync(bucketName, objectName, (stream) => { skipUpload = false; } - if (!skipUpload) { + numPartsUploaded += 1; string etag = await this.PutObjectAsync(bucketName, objectName, uploadId, partNumber, dataToCopy, metaData, cancellationToken); totalParts[partNumber - 1] = new Part() { PartNumber = partNumber, ETag = etag, size = (long)expectedReadSize }; } } + // This shouldn't happen where stream size is known. + if (partCount != numPartsUploaded && size != -1) + { + await this.RemoveUploadAsync(bucketName, objectName, uploadId, cancellationToken); + return; + } + Dictionary etags = new Dictionary(); - for (partNumber = 1; partNumber <= partCount; partNumber++) + for (partNumber = 1; partNumber <= numPartsUploaded; partNumber++) { etags[partNumber] = totalParts[partNumber - 1].ETag; } await this.CompleteMultipartUploadAsync(bucketName, objectName, uploadId, etags, cancellationToken); - } + /// /// Internal method to complete multi part upload of object to server. ///