Information about file to upload
예제 #1
0
        private static Stream GetMultipartFormPre(SendFileInfo file, long filelength, string boundry)
        {
            var result = new MemoryStream(1000);

            using (var writer = new StreamWriter(result, UTF8, 16, true))
            {
                if (file.Parameters != null)
                {
                    foreach (var pair in file.Parameters)
                    {
                        writer.Write($"--{boundry}\r\n");
                        writer.Write($"Content-Disposition: form-data; name=\"{pair.Key}\"\r\n\r\n{pair.Value}\r\n");
                    }
                }

                writer.Write($"--{boundry}\r\n");
                writer.Write($"Content-Disposition: form-data; name=\"{file.FormName}\"; filename={file.FileName}\r\n");
                writer.Write($"Content-Type: application/octet-stream\r\n");

                writer.Write($"Content-Length: {filelength}\r\n\r\n");
            }

            result.Position = 0;
            return(result);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        /// <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;

                    string 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))
                        {
                            if (file.CancellationToken != null)
                            {
                                var token = (CancellationToken)file.CancellationToken;
                                await pre.CopyToAsync(output, 81920).ConfigureAwait(false);
                                //await input.CopyToAsync(output, 81920).ConfigureAwait(false);
                                await CopyToStreamAsync(input, output, 81920, token, file.Progress).ConfigureAwait(false);
                                if (token.IsCancellationRequested)
                                {
                                    client.Abort();
                                    throw new OperationCanceledException(token);
                                }
                                await post.CopyToAsync(output, 81920).ConfigureAwait(false);
                            }
                            else
                            {
                                await pre.CopyToAsync(output).ConfigureAwait(false);
                                await input.CopyToAsync(output).ConfigureAwait(false);
                                await post.CopyToAsync(output).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);
        }