/// <summary> /// Write a slice of data using the UploadSliceRequest. /// </summary> /// <param name="uploadSliceRequest">The UploadSliceRequest to make the request with.</param> /// <param name="exceptionTrackingList">A list of exceptions to use to track progress. SlicedUpload may retry.</param> private async Task <UploadResult <T> > UploadSliceAsync(UploadSliceRequest <T> uploadSliceRequest, ICollection <Exception> exceptionTrackingList) { var firstAttempt = true; this._uploadStream.Seek(uploadSliceRequest.RangeBegin, SeekOrigin.Begin); while (true) { using (var requestBodyStream = new ReadOnlySubStream(this._uploadStream, uploadSliceRequest.RangeBegin, uploadSliceRequest.RangeLength)) { try { return(await uploadSliceRequest.PutAsync(requestBodyStream).ConfigureAwait(false)); } catch (ServiceException exception) { if (exception.IsMatch("generalException") || exception.IsMatch("timeout")) { if (firstAttempt) { firstAttempt = false; exceptionTrackingList.Add(exception); } else { throw; } } else if (exception.IsMatch("invalidRange")) { // Succeeded previously, but nothing to return right now return(new UploadResult <T>()); } else { throw; } } } } }
/// <summary> /// Get the series of requests needed to complete the upload session. Call <see cref="UpdateSessionStatusAsync"/> /// first to update the internal session information. /// </summary> /// <returns>All requests currently needed to complete the upload session.</returns> internal IEnumerable <UploadSliceRequest <T> > GetUploadSliceRequests() { foreach (var(item1, item2) in this._rangesRemaining) { var currentRangeBegins = item1; while (currentRangeBegins <= item2) { var nextSliceSize = NextSliceSize(currentRangeBegins, item2); var uploadRequest = new UploadSliceRequest <T>( this.Session.UploadUrl, this._client, currentRangeBegins, currentRangeBegins + nextSliceSize - 1, this.TotalUploadLength); yield return(uploadRequest); currentRangeBegins += nextSliceSize; } } }