/// <summary> /// Add progress reporting for the specified response message. /// </summary> /// <param name="response"> /// The HTTP response message. /// </param> /// <param name="progressSink"> /// An optional sink that will receive raw progress data. /// </param> /// <param name="bufferSize"> /// An optional buffer size to use when transferring content. /// /// If not specified, the default buffer size is used. /// </param> /// <returns> /// The response message. /// </returns> public static HttpResponseMessage AddProgress(this HttpResponseMessage response, IProgressSink <long> progressSink = null, int?bufferSize = null) { if (response == null) { throw new ArgumentNullException(nameof(response)); } // No response content? No progress to report. // Might be worth creating a dummy sink that just emits 100% progress. if (response.Content == null) { return(response); } if (response.Content is ProgressContent) { throw new InvalidOperationException("The HTTP response message has already been configured to report progress."); } response.Content = new ProgressContent( innerContent: response.Content, sink: progressSink ?? DefaultSink.Int64(), bufferSize: bufferSize ); return(response); }
/// <summary> /// Wrap the specified stream in a <see cref="ProgressStream"/> that will report progress for reads. /// </summary> /// <param name="stream"> /// The stream to wrap. /// </param> /// <param name="total"> /// An optional total used to calculate progress. /// /// If not specified, the stream length is used (providing the stream supports seeking). /// </param> /// <param name="progressObserver"> /// An optional <see cref="IObserver{TValue}"/> that receives raw progress data. /// </param> /// <param name="ownsStream"> /// Should the <see cref="ProgressStream"/> close the inner stream when it is closed? /// </param> /// <returns> /// The new <see cref="ProgressStream"/>. /// </returns> /// <exception cref="InvalidOperationException"> /// The <paramref name="stream"/> is already a <see cref="ProgressStream"/>. /// <paramref name="total"/> was not specified, and the stream does not support seeking. /// </exception> public static ProgressStream WithReadProgress(this Stream stream, long?total = null, IObserver <RawProgressData <long> > progressObserver = null, bool ownsStream = true) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } IProgressSink <long> sink = DefaultSink.Int64(); if (total.HasValue) { sink.Total = total.Value; } else if (stream.CanSeek) { sink.Total = stream.Length; } else { throw new InvalidOperationException("Total was not specified, and cannot be auto-detected because the specified stream does not support seeking."); } if (progressObserver != null) { sink.Subscribe(progressObserver); } return(new ProgressStream(stream, StreamDirection.Read, ownsStream, sink)); }
/// <summary> /// Add progress reporting for the specified request message. /// </summary> /// <param name="request"> /// The HTTP request message. /// </param> /// <param name="progressSink"> /// An optional sink that will receive raw progress data. /// </param> /// <param name="bufferSize"> /// An optional buffer size to use when transferring content. /// /// If not specified, the default buffer size is used. /// </param> /// <returns> /// The request message. /// </returns> public static HttpRequestMessage AddProgress(this HttpRequestMessage request, IProgressSink <long> progressSink = null, int?bufferSize = null) { if (request == null) { throw new ArgumentNullException(nameof(request)); } // No response content? No progress to report. if (request.Content == null) { return(request); } if (request.Content is ProgressContent) { throw new InvalidOperationException("The HTTP request message has already been configured to report progress."); } request.Content = new ProgressContent( innerContent: request.Content, sink: progressSink ?? DefaultSink.Int64(), bufferSize: bufferSize ); request.SetProgressContextId(ProgressContext.Current.Id); return(request); }
/// <summary> /// Wrap the specified stream in a <see cref="ProgressStream"/> that will report progress for writes. /// </summary> /// <param name="stream"> /// The stream to wrap. /// </param> /// <param name="total"> /// The total used to calculate progress. /// </param> /// <param name="progressObserver"> /// An optional <see cref="IObserver{TValue}"/> that receives raw progress data. /// </param> /// <param name="ownsStream"> /// Should the <see cref="ProgressStream"/> close the inner stream when it is closed? /// </param> /// <returns> /// The new <see cref="ProgressStream"/>. /// </returns> /// <exception cref="InvalidOperationException"> /// The <paramref name="stream"/> is already a <see cref="ProgressStream"/>. /// </exception> public static ProgressStream WithWriteProgress(this Stream stream, long total, IObserver <RawProgressData <long> > progressObserver = null, bool ownsStream = true) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } IProgressSink <long> sink = DefaultSink.Int64(); if (progressObserver != null) { sink.Subscribe(progressObserver); } return(new ProgressStream(stream, StreamDirection.Write, ownsStream, sink)); }