Отправка файла (пара гигабайт) на сервер с отображением прогресса, скорости и т.д - 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); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д