public async Task WriteToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null) { byte[] buffer = null; foreach (Stream currentStream in streams) { currentStream.Position = 0; if (cancellationToken.IsCancellationRequested) return; // Purely for progress purposes double totalRead = new double(); if (currentStream is MemoryStream) { // MemoryStream: Get underlying buffer MemoryStream memoryStream = (MemoryStream)currentStream; // MemoryStream: Check if underlying buffer is valid bool bufferValid = false; try { buffer = memoryStream.GetBuffer(); bufferValid = buffer != null; } catch { } if (bufferValid) { // MemoryStream Buffer: Buffer is valid and can be used int readPosition = new int(); while (readPosition < memoryStream.Length && !cancellationToken.IsCancellationRequested) { // ProgressHandler: Begin asynchronous invoke IAsyncResult progressHandlerResult = null; if (progressHandler != null) progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, totalRead / (double)_length), null, null); // WriteTask: Start writing to stream asynchronously int chunk = (int) Math.Min(memoryStream.Length - readPosition, bufferSize); Task writeTask = destination.WriteAsync(buffer, readPosition, chunk, cancellationToken); // ProgressHandler: End asynchronous invoke if (progressHandler != null && progressHandlerResult != null) progressHandler.EndInvoke(progressHandlerResult); // WriteTask: Wait for chunk upload to finish await writeTask; totalRead += chunk; readPosition += chunk; } // Go onto next stream continue; } // MemoryStream Buffer: Buffer was not valid - fall through to next case } if (buffer == null || buffer.Length < bufferSize) buffer = new byte[bufferSize]; int chunkRead; while ((chunkRead = await currentStream.ReadAsync(buffer, 0, bufferSize)) > 0 && !cancellationToken.IsCancellationRequested) { // ProgressHandler: Begin asynchronous invoke IAsyncResult progressHandlerResult = null; if (progressHandler != null) progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)totalRead / (double)_length), null, null); // WriteTask: Start writing to stream asynchronously Task writeTask = destination.WriteAsync(buffer, 0, chunkRead, cancellationToken); // ProgressHandler: End asynchronous invoke if (progressHandler != null && progressHandlerResult != null) progressHandler.EndInvoke(progressHandlerResult); // WriteTask: Wait for write to finish await writeTask; totalRead += chunkRead; } } }
/// <summary> /// Asynchronously reads the content of an HTTP response as a UTF-8 encoded string. /// </summary> /// <param name="response">Required. The HttpWebResponse object representing the response to read.</param> /// <param name="disposeResponse">Optional. A boolean value determining whether to dispose of the response when finished. The default is true.</param> /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param> /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param> /// <param name="completeHandler">Optional. The event handler to invoke when the response has been read.</param> /// <returns>Returns a Task object containing a string result representing the content of the response.</returns> public static async Task<string> ToUTF8Async(this HttpWebResponse response, bool disposeResponse = true, CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null) { return Encoding.UTF8.GetString(await ToArrayAsync(response, disposeResponse, cancellationToken, progressHandler, completeHandler)); }
/// <summary> /// Asynchronously performs an HttpWebRequest with request data. /// </summary> /// <param name="request">Required. The HttpWebRequest to represent the base request.</param> /// <param name="contentType">Required. The Content-Type HTTP header to send with the request.</param> /// <param name="data">Required. A byte array representing the request data to send with the request.</param> /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param> /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param> /// <param name="completeHandler">Optional. The event handler to invoke when the request has finished.</param> /// <returns>Returns a HttpWebResponse representing the response from the server.</returns> public async Task<HttpWebResponse> RequestAsync(HttpWebRequest request, string contentType, byte[] data, CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null) { request.ContentLength = (data != null) ? data.Length : 0; if (!String.IsNullOrEmpty(contentType)) request.ContentType = contentType; // Write to request stream using (Stream requestStream = await request.GetRequestStreamAsync()) { int bufferSize = GetOptimalBufferSize(data.Length); int bytesDone = new int(); while (bytesDone < data.Length) { // ProgressHandler: Begin asynchronous invoke IAsyncResult progressHandlerResult = null; if (progressHandler != null) progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesDone / (double)data.Length), null, null); // WriteTask: Start writing to stream asynchronously int nextChunkSize = Math.Min(data.Length - bytesDone, bufferSize); Task writeTask = requestStream.WriteAsync(data, bytesDone, nextChunkSize, cancellationToken); // End asynchronous ProgressHandler if (progressHandler != null && progressHandlerResult != null) progressHandler.EndInvoke(progressHandlerResult); // WriteTask: Wait for chunk upload to finish await writeTask; bytesDone += nextChunkSize; } } HttpWebResponse result; { // HttpWebResponse: Start task Task<WebResponse> resultTask = request.GetResponseAsync(); // CompleteHandler: Begin asynchronous invoke IAsyncResult completeHandlerResult = null; if (completeHandler != null) completeHandler.BeginInvoke(null, null); // HttpWebResponse: Await result result = (HttpWebResponse)(await resultTask); // CompleteHandler: End asynchronous invoke if (completeHandler != null && completeHandlerResult != null) completeHandler.EndInvoke(completeHandlerResult); } return result; }
/// <summary> /// Asynchronously reads the content of an HTTP response to a byte array. /// </summary> /// <param name="response">Required. The HttpWebResponse object representing the response to read.</param> /// <param name="disposeResponse">Optional. A boolean value determining whether to dispose of the response when finished. The default is true.</param> /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param> /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param> /// <param name="completeHandler">Optional. The event handler to invoke when the response has been read.</param> /// <returns>Returns a Task object containing a byte array result representing the content of the response.</returns> public static async Task<byte[]> ToArrayAsync(this HttpWebResponse response, bool disposeResponse = true, CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null) { byte[] result; if (response.ContentLength > 0) { long contentLength = response.ContentLength; result = new byte[contentLength]; int bufferSize = Http_Old.GetOptimalBufferSize(contentLength); using (Stream responseStream = response.GetResponseStream()) { long bytesRead = 0; // ReadTask: Start reading before first iteration. int chunkRead = await responseStream.ReadAsync(result, 0, (int)Math.Min(contentLength - bytesRead, bufferSize), cancellationToken); bytesRead += chunkRead; while (bytesRead < contentLength && chunkRead > 0 && !cancellationToken.IsCancellationRequested) { // ProgressHandler: Begin asynchronous invoke IAsyncResult progressHandlerResult = null; if (progressHandler != null) progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesRead / (double)contentLength), null, null); // ReadTask: Start another read asynchronously Task<int> readTask = responseStream.ReadAsync(result, 0, (int)Math.Min(contentLength - bytesRead, bufferSize), cancellationToken); // ProgressHandler: End asynchronous invoke if (progressHandler != null && progressHandlerResult != null) progressHandler.EndInvoke(progressHandlerResult); // WriteTask: Wait for chunk to finish chunkRead = await readTask; bytesRead += chunkRead; } } } else { int bufferSize = Http_Old.GetOptimalBufferSize(-1); using (MemoryStream memory = new MemoryStream(bufferSize)) { using (Stream responseStream = response.GetResponseStream()) { byte[] buffer = new byte[bufferSize]; long bytesRead = 0; int chunkRead; while ((chunkRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0) { // ProgressHandler: Begin asynchronous invoke IAsyncResult progressHandlerResult = null; if (progressHandler != null && response.ContentLength > 0) progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesRead / (double)response.ContentLength), null, null); // WriteTask: Start writing to memory asynchronously Task writeTask = memory.WriteAsync(buffer, 0, chunkRead, cancellationToken); // End asynchronous ProgressHandler if (progressHandler != null && progressHandlerResult != null) progressHandler.EndInvoke(progressHandlerResult); // WriteTask: Wait for chunk to finish await writeTask; bytesRead += chunkRead; } } result = memory.ToArray(); } } if (disposeResponse) response.Close(); return result; }
/// <summary> /// Asynchronously performs an HttpWebRequest with request data. /// </summary> /// <param name="request">Required. The HttpWebRequest to represent the base request.</param> /// <param name="contentType">Required. The Content-Type HTTP header to send with the request.</param> /// <param name="formData">Required. A FormBuilder object representing the form data to send.</param> /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param> /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param> /// <param name="completeHandler">Optional. The event handler to invoke when the request has finished.</param> /// <returns>Returns a HttpWebResponse representing the response from the server.</returns> public async Task<HttpWebResponse> RequestAsync(HttpWebRequest request, FormBuilder formData, CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null) { request.ContentLength = formData.Length; if (!String.IsNullOrEmpty(formData.ContentType)) request.ContentType = formData.ContentType; // Write to request stream using (Stream requestStream = await request.GetRequestStreamAsync()) { await formData.WriteToAsync(requestStream, GetOptimalBufferSize(formData.Length)); } HttpWebResponse result; { // HttpWebResponse: Start task Task<WebResponse> resultTask = request.GetResponseAsync(); // CompleteHandler: Begin asynchronous invoke IAsyncResult completeHandlerResult = null; if (completeHandler != null) completeHandler.BeginInvoke(null, null); // HttpWebResponse: Await result result = (HttpWebResponse)(await resultTask); // CompleteHandler: End asynchronous invoke if (completeHandler != null && completeHandlerResult != null) completeHandler.EndInvoke(completeHandlerResult); } return result; }