Use this class to make resumable uploads or to upload large files. This class allows the client to control the size of chunks uploaded (for example, can be useful to use small chunks if the connection is slow). Also allows the client to pause an upload and resume later.
        /// <inheritdoc/>
        public async Task <IOneDriveStorageFile> UploadFileAsync(string desiredName, IRandomAccessStream content, CreationCollisionOption options = CreationCollisionOption.FailIfExists, int maxChunkSize = -1)
        {
            int currentChunkSize = maxChunkSize < 0 ? OneDriveUploadConstants.DefaultMaxChunkSizeForUploadSession : maxChunkSize;

            if (currentChunkSize % OneDriveUploadConstants.RequiredChunkSizeIncrementForUploadSession != 0)
            {
                throw new ArgumentException("Max chunk size must be a multiple of 320 KiB", nameof(maxChunkSize));
            }

            if (string.IsNullOrEmpty(desiredName))
            {
                throw new ArgumentNullException(nameof(desiredName));
            }

            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            var uploadSessionUri = $"{Provider.BaseUrl}/drive/items/{OneDriveItem.Id}:/{desiredName}:/oneDrive.createSession";

            var conflictBehavior = new OneDriveItemConflictBehavior {
                Item = new OneDriveConflictItem {
                    ConflictBehavior = OneDriveHelper.TransformCollisionOptionToConflictBehavior(options.ToString())
                }
            };

            var jsonConflictBehavior   = JsonConvert.SerializeObject(conflictBehavior);
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uploadSessionUri)
            {
                Content = new StringContent(jsonConflictBehavior, Encoding.UTF8, "application/json")
            };
            await Provider.AuthenticationProvider.AuthenticateRequestAsync(request).ConfigureAwait(false);

            var response = await Provider.HttpProvider.SendAsync(request).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                throw new ServiceException(new Error {
                    Message = "Could not create an UploadSession", Code = "NoUploadSession", ThrowSite = "UWP Community Toolkit"
                });
            }

            IsUploadCompleted = false;
            var jsonData = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            _uploadSession = JsonConvert.DeserializeObject <Microsoft.OneDrive.Sdk.UploadSession>(jsonData);

            var streamToUpload = content.AsStreamForRead();

            _uploadProvider = new Microsoft.OneDrive.Sdk.Helpers.ChunkedUploadProvider(_uploadSession, Provider, streamToUpload, maxChunkSize);

            var uploadedItem = await _uploadProvider.UploadAsync().ConfigureAwait(false);

            IsUploadCompleted = true;

            return(InitializeOneDriveStorageFile(uploadedItem.CopyToDriveItem()));
        }
        public void ConstructorTest_InvalidChunkSize()
        {
            this.StreamSetup(false);

            var uploadProvider = new ChunkedUploadProvider(
                this.uploadSession.Object,
                this.client.Object,
                this.uploadStream.Object,
                12);
        }
        public void ConstructorTest_Valid()
        {
            this.StreamSetup(true);

            var uploadProvider = new ChunkedUploadProvider(
                this.uploadSession.Object, 
                this.client.Object,
                this.uploadStream.Object,
                320*1024);
        }
        private UploadChunkResult SetupGetChunkResponseTest(ServiceException serviceException = null, bool failsOnce = true, bool verifyTrackedExceptions = true)
        {
            var chunkSize = 320 * 1024;
            var bytesToUpload = new byte[] { 4, 8, 15, 16 };
            var trackedExceptions = new List<Exception>();
            this.uploadSession.Object.NextExpectedRanges = new[] { "0-" };
            var stream = new MemoryStream(bytesToUpload.Length);
            stream.Write(bytesToUpload, 0, bytesToUpload.Length);
            stream.Seek(0, SeekOrigin.Begin);

            var provider = new ChunkedUploadProvider(
                this.uploadSession.Object,
                this.client.Object,
                stream,
                chunkSize);

            var mockRequest = new Mock<UploadChunkRequest>(
                this.uploadSession.Object.UploadUrl,
                this.client.Object,
                null,
                0,
                bytesToUpload.Length - 1,
                bytesToUpload.Length);

            if (serviceException != null && failsOnce)
            {
                mockRequest.SetupSequence(r => r.PutAsync(
                    It.IsAny<Stream>(),
                    It.IsAny<CancellationToken>()))
                    .Throws(serviceException)
                    .Returns(Task.FromResult(new UploadChunkResult() { ItemResponse = new Item()}));
            }
            else if (serviceException != null)
            {
                mockRequest.Setup(r => r.PutAsync(
                    It.IsAny<Stream>(),
                    It.IsAny<CancellationToken>()))
                    .Throws(serviceException);
            }
            else
            {
                mockRequest.Setup(r => r.PutAsync(
                    It.IsAny<Stream>(),
                    It.IsAny<CancellationToken>()))
                    .Returns(Task.FromResult(new UploadChunkResult { ItemResponse = new Item()}));
            }

            var task = provider.GetChunkRequestResponseAsync(mockRequest.Object, bytesToUpload, trackedExceptions);
            try
            {
                task.Wait();
            }
            catch (AggregateException exception)
            {
                throw exception.InnerException;
            }

            if (verifyTrackedExceptions)
            {
                Assert.IsTrue(trackedExceptions.Contains(serviceException), "Expected ServiceException in TrackedException list");
            }

            return task.Result;
        }
        private IEnumerable<UploadChunkRequest> SetupGetUploadChunksTest(int chunkSize, long totalSize, IEnumerable<string> ranges)
        {
            this.uploadSession.Object.NextExpectedRanges = ranges;
            this.uploadStream = new Mock<Stream>();
            this.uploadStream.Setup(s => s.Length).Returns(totalSize);
            this.StreamSetup(true);

            var provider = new ChunkedUploadProvider(
                this.uploadSession.Object,
                this.client.Object,
                this.uploadStream.Object,
                chunkSize);

            return provider.GetUploadChunkRequests();
        }