Отправка файла (пара гигабайт) на сервер с отображением прогресса, скорости и т.д - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. В домашних условиях была самому себе поставлена задача залить файл со своего ноута на домашний минисервачок. Подымать фтп-сервер, а потом на него фаерзилой лить? Неее! Яжпрограмист! Сам напишу! Прога (клиент, который отправляет) должна показывать прогресс отправки со скоростью, сколько времени осталось, сколько прошло и т.д., также желательно, но не обязательно, авторизация на сервере перед отправкой. Погуглил, вспомнил, что когда-то делал, нашёл несколько вариантов вообще какой-либо возможности что-либо сделать по сети: 1) Socket.Send(byte[]) - тут всё равно что лить, даже знаю как научить сервер принимать, но преобразовывать несколькогигабайтный файл в массив байт для отправки как-то не оч хочется) 2) FileWebRequest - нашёл пример на мсдн-е (https://msdn.microsoft.com/ru-ru/lib...v=vs.110).aspx) но так и не понял как он должен работать 3) FtpWebRequest - аналогично п.2 (https://msdn.microsoft.com/ru-ru/lib...v=vs.110).aspx) 4) HttpWebRequest - знаю, что можно скачать, но можно ли залить хз 5) WebClient.UploadFile(string <куда лить>, string <что лить>) - читал, что тут нельзя реализовать авторизацию, так что он последний в очереди на рассмотрение Хотелось бы знать какой из них проще реализовать и что-бы он был наименее костыльным. И самый главный вопрос: как научить сервер принимать этот самый файл в случае п.2-5?

Решение задачи: «Отправка файла (пара гигабайт) на сервер с отображением прогресса, скорости и т.д»

textual
Листинг программы
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading.Tasks;
 
namespace ConsoleApplication297
{
    internal class Program
    {
        private static void Main()
        {
            using (var server = new Server(IPAddress.Loopback, 5345))
            {
                var serverTask = server.Start();
                using (var httpClient = new HttpClient())
                {
                    var response = httpClient.PostAsync(new Uri("http://localhost:5345/Test"),
                            new ProgressableStreamContent(File.OpenRead("bigFile.blob"),
                                (uploaded, size) => Console.WriteLine($"Bytes sent {uploaded} of {size}"))).GetAwaiter()
                        .GetResult();
 
                    var message = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
 
                    Console.WriteLine(message);
                }
 
                serverTask.GetAwaiter().GetResult();
            }
        }
    }
 
    internal class ProgressableStreamContent : HttpContent
    {
        private const int ChunkSize = 4096;
        private readonly Stream _content;
        private readonly Action<long, long> _progress;
 
        public ProgressableStreamContent(Stream content, Action<long, long> progress)
        {
            _content = content ?? throw new ArgumentNullException(nameof(content));
 
            _progress = progress ?? ((_, __) => { });
        }
 
        protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            var buffer = new byte[ChunkSize];
            TryComputeLength(out var size);
            var uploaded = 0;
 
            using (_content)
            {
                while (true)
                {
                    var length = await _content.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
                    if (length <= 0) break;
 
                    uploaded += length;
                    _progress(uploaded, size);
 
                    await stream.WriteAsync(buffer, 0, length).ConfigureAwait(false);
                    stream.Flush();
                }
            }
 
            stream.Flush();
        }
 
        protected override bool TryComputeLength(out long length)
        {
            length = _content.Length;
            return true;
        }
    }
 
    internal class Server : IDisposable
    {
        private readonly TcpListener _server;
 
        public Server(IPAddress ipAddress, int port) => _server = new TcpListener(ipAddress, port);
 
        public void Dispose() => _server.Stop();
 
        public async Task Start()
        {
            _server.Start();
            var client = await _server.AcceptTcpClientAsync().ConfigureAwait(false);
 
            if (!client.Connected)
                throw new Exception("Client not connected.");
 
            var stream = client.GetStream();
 
            using (var fileStream = File.Create("saved.blob"))
                await fileStream.CopyToAsync(stream).ConfigureAwait(false);
 
 
            var content = "DONE!";
            var writer = new StreamWriter(stream);
            await writer.WriteAsync("HTTP/1.0 200 OK").ConfigureAwait(false);
            await writer.WriteAsync(Environment.NewLine).ConfigureAwait(false);
            await writer.WriteAsync("Content-Type: text/plain; charset=UTF-8").ConfigureAwait(false);
            await writer.WriteAsync(Environment.NewLine).ConfigureAwait(false);
            await writer.WriteAsync("Content-Length: " + content.Length).ConfigureAwait(false);
            await writer.WriteAsync(Environment.NewLine).ConfigureAwait(false);
            await writer.WriteAsync(Environment.NewLine).ConfigureAwait(false);
            await writer.WriteAsync(content).ConfigureAwait(false);
            await writer.FlushAsync().ConfigureAwait(false);
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4 из 5
Похожие ответы