/// <summary> /// Uploads file /// </summary> /// <typeparam name="TResult">Result type</typeparam> /// <param name="method">HTTP method</param> /// <param name="url">URL for request</param> /// <param name="fileInfo">File upload parameters. Input stream must support Length</param> /// <returns>Async result object</returns> public async Task <TResult> SendFile <TResult>(HttpMethod method, string url, SendFileInfo fileInfo) { var result = default(TResult); await Retry.Do( RetryTimes, RetryDelay, async() => { var client = await GetHttpClient(url); try { client.Method = method.ToString(); client.AllowWriteStreamBuffering = false; var boundry = Guid.NewGuid().ToString(); client.ContentType = $"multipart/form-data; boundary={fileInfo.MultipartBoundary.Boundary}"; client.SendChunked = false; using (var input = fileInfo.StreamOpener()) { var preFix = fileInfo.MultipartBoundary.GetPrefix(input); var postFix = fileInfo.MultipartBoundary.Postfix; client.ContentLength = preFix.Length + input.Length + postFix.Length; fileInfo.CancellationToken.ThrowIfCancellationRequested(); using (var output = await client.GetRequestStreamAsync()) { var state = new CopyStreamState(); await CopyStreams(preFix, output, fileInfo, null); await CopyStreams(input, output, fileInfo, state); await CopyStreams(postFix, output, fileInfo, null); } } using (var response = (HttpWebResponse)await client.GetResponseAsync()) { if (!response.IsSuccessStatusCode()) { return(await LogBadResponse(response)); } result = await response.ReadAsAsync <TResult>(); } return(true); } catch (Exception) { client.Abort(); throw; } }, FileSendExceptionProcessor); return(result); }
/// <summary> /// Uploads file /// </summary> /// <typeparam name="R">Result type</typeparam> /// <param name="method">HTTP method</param> /// <param name="url">URL for request</param> /// <param name="file">File upload parameters. Input stream must support Length</param> /// <returns>Async result object</returns> public async Task <R> SendFile <R>(HttpMethod method, string url, SendFileInfo file) { R result = default(R); await Retry.Do( RetryTimes, RetryDelay, async() => { var client = await GetHttpClient(url).ConfigureAwait(false); try { client.Method = method.ToString(); client.AllowWriteStreamBuffering = false; var boundry = Guid.NewGuid().ToString(); client.ContentType = $"multipart/form-data; boundary={boundry}"; client.SendChunked = true; using (var input = file.StreamOpener()) { var pre = GetMultipartFormPre(file, input.Length, boundry); var post = GetMultipartFormPost(boundry); client.ContentLength = pre.Length + input.Length + post.Length; using (var output = await client.GetRequestStreamAsync().ConfigureAwait(false)) { var state = new CopyStreamState(); await CopyStreams(pre, output, file, state).ConfigureAwait(false); await CopyStreams(input, output, file, state).ConfigureAwait(false); await CopyStreams(post, output, file, state).ConfigureAwait(false); } } using (var response = (HttpWebResponse)await client.GetResponseAsync().ConfigureAwait(false)) { if (!response.IsSuccessStatusCode()) { return(await LogBadResponse(response).ConfigureAwait(false)); } result = await response.ReadAsAsync <R>().ConfigureAwait(false); } return(true); } catch (Exception) { client.Abort(); throw; } }, GeneralExceptionProcessor).ConfigureAwait(false); return(result); }
private static async Task CopyStreams(Stream source, Stream destination, SendFileInfo info, CopyStreamState state) { var buffer = new byte[info.BufferSize]; int bytesRead; while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0) { if (info.CancellationToken != null && info.CancellationToken.Value.IsCancellationRequested) { throw new TaskCanceledException(); } await destination.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); state.Pos += bytesRead; if (info.Progress != null && state.Pos >= state.NextPos) { state.NextPos = info.Progress.Invoke(state.Pos); } } }
private static async Task CopyStreams(Stream source, Stream destination, SendFileInfo info, CopyStreamState state) { var buffer = new byte[info.BufferSize]; int bytesRead; var lastProgessCalled = false; while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, info.CancellationToken)) > 0) { await destination.WriteAsync(buffer, 0, bytesRead, info.CancellationToken); lastProgessCalled = false; if (state != null) { state.Pos += bytesRead; if (info.Progress != null && (state.Pos >= state.NextPos)) { state.NextPos = await info.Progress.Invoke(state.Pos); lastProgessCalled = true; } } } if (state != null && info.Progress != null && !lastProgessCalled) { await info.Progress.Invoke(state.Pos); } }