C# Send and receive big file via stream

//sender;
class FileSender
{
    private readonly HttpClient _httpClient;

    public FileSender()
    {
        _httpClient = new HttpClient
        {
            Timeout = TimeSpan.FromHours(2) // 2小时超时
        };
    }

    public async Task<bool> SendFileAsync(string filePath, string serverUrl,
        IProgress<UploadProgress> progress = null)
    {
        if (!File.Exists(filePath))
        {
            Console.WriteLine($"文件不存在: {filePath}");
            return false;
        }

        var fileInfo = new FileInfo(filePath);
        var fileName = Path.GetFileName(filePath);

        Console.WriteLine($"开始上传文件: {fileName}");
        Console.WriteLine($"文件大小: {FormatFileSize(fileInfo.Length)}");

        try
        {
            await using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                var content = new ProgressStreamContent(fileStream, progress, fileName);

                var response = await _httpClient.PostAsync(serverUrl, content);

                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsStringAsync();
                    Console.WriteLine($"上传成功: {result}");
                    return true;
                }
                else
                {
                    Console.WriteLine($"上传失败: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}");
                    return false;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"上传过程中出错: {ex.Message}");
            return false;
        }
    }

    private string FormatFileSize(long bytes)
    {
        string[] sizes = { "B", "KB", "MB", "GB", "TB" };
        int order = 0;
        double len = bytes;
        while (len >= 1024 && order < sizes.Length - 1)
        {
            order++;
            len /= 1024;
        }
        return $"{len:0.##} {sizes[order]}";
    }
}

public class UploadProgress
{
    public long BytesRead { get; set; }
    public long TotalBytes { get; set; }
    public double ProgressPercentage => TotalBytes > 0 ? (BytesRead * 100.0) / TotalBytes : 0;
    public double Speed { get; set; } // bytes per second
}

class ProgressStreamContent : StreamContent
{
    private readonly Stream _stream;
    private readonly IProgress<UploadProgress> _progress;
    private readonly string _fileName;
    private readonly long _totalBytes;
    private long _bytesRead;
    private readonly System.Diagnostics.Stopwatch _stopwatch;

    public ProgressStreamContent(Stream stream, IProgress<UploadProgress> progress, string fileName)
        : base(stream)
    {
        _stream = stream;
        _progress = progress;
        _fileName = fileName;
        _totalBytes = stream.Length;
        _bytesRead = 0;
        _stopwatch = System.Diagnostics.Stopwatch.StartNew();
    }

    protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        var buffer = new byte[81920]; // 80KB buffer
        int read;

        while ((read = await _stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await stream.WriteAsync(buffer, 0, read);
            _bytesRead += read;

            // 计算速度
            var elapsedSeconds = _stopwatch.Elapsed.TotalSeconds;
            var speed = elapsedSeconds > 0 ? _bytesRead / elapsedSeconds : 0;

            _progress?.Report(new UploadProgress
            {
                BytesRead = _bytesRead,
                TotalBytes = _totalBytes,
                Speed = speed
            });
        }
    }

    protected override bool TryComputeLength(out long length)
    {
        length = _totalBytes;
        return true;
    }
}

//Receiver

 class FileReceiver
 {
     private readonly HttpListener _listener;
     private readonly string _saveDirectory;

     public FileReceiver(string prefix, string saveDirectory)
     {
         _listener = new HttpListener();
         _listener.Prefixes.Add(prefix);
         _saveDirectory = saveDirectory;
         Directory.CreateDirectory(saveDirectory);
     }

     public async Task StartAsync()
     {
         _listener.Start();
         Console.WriteLine("文件接收服务已启动...");
         Console.WriteLine("等待文件上传...");

         while (true)
         {
             try
             {
                 var context = await _listener.GetContextAsync();
                 _ = Task.Run(() => ProcessRequestAsync(context));
             }
             catch (Exception ex)
             {
                 Console.WriteLine($"接收错误: {ex.Message}");
             }
         }
     }

     private async Task ProcessRequestAsync(HttpListenerContext context)
     {
         var request = context.Request;
         var response = context.Response;

         try
         {
             if (request.HttpMethod == "POST")
             {
                 // 获取文件名
                 var fileName = request.Headers["X-FileName"] ?? "unknown_file.dat";
                 var filePath = Path.Combine(_saveDirectory, fileName);

                 Console.WriteLine($"开始接收文件: {fileName}");
                 var stopwatch = System.Diagnostics.Stopwatch.StartNew();

                 // 流式接收文件
                 await using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                 {
                     await request.InputStream.CopyToAsync(fileStream);
                 }

                 stopwatch.Stop();
                 var fileInfo = new FileInfo(filePath);
                 Console.WriteLine($"文件接收完成: {fileName}");
                 Console.WriteLine($"文件大小: {FormatFileSize(fileInfo.Length)}");
                 Console.WriteLine($"耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒");
                 Console.WriteLine($"平均速度: {FormatFileSize((long)(fileInfo.Length / stopwatch.Elapsed.TotalSeconds))}/s");

                 // 发送成功响应
                 response.StatusCode = 200;
                 await using (var writer = new StreamWriter(response.OutputStream))
                 {
                     await writer.WriteAsync("文件上传成功");
                 }
             }
             else
             {
                 response.StatusCode = 405;
                 await using (var writer = new StreamWriter(response.OutputStream))
                 {
                     await writer.WriteAsync("只支持 POST 方法");
                 }
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine($"处理请求时出错: {ex.Message}");
             response.StatusCode = 500;
             await using (var writer = new StreamWriter(response.OutputStream))
             {
                 await writer.WriteAsync($"服务器错误: {ex.Message}");
             }
         }
         finally
         {
             response.Close();
         }
     }

     private string FormatFileSize(long bytes)
     {
         string[] sizes = { "B", "KB", "MB", "GB", "TB" };
         int order = 0;
         double len = bytes;
         while (len >= 1024 && order < sizes.Length - 1)
         {
             order++;
             len /= 1024;
         }
         return $"{len:0.##} {sizes[order]}";
     }

     public void Stop()
     {
         _listener?.Stop();
         _listener?.Close();
     }
 }

 

 

 

image

 

 

image

 

 

 

//sender
using System.Net;
using System.Text;

namespace ConsoleApp13
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            // 设置控制台输出编码为 UTF-8
            Console.OutputEncoding = Encoding.UTF8;
            // 设置控制台输入编码为 UTF-8
            Console.InputEncoding = Encoding.UTF8;
            Console.WriteLine("=== 大文件发送端 (ConsoleA) ===");

            // 配置
            string filePath = @"E:\KXWC\kxwc1.ts";
            string serverUrl = "http://localhost:8080/upload/";

            // 创建进度报告器
            var progress = new Progress<UploadProgress>(report =>
            {
                Console.SetCursorPosition(0, Console.CursorTop);
                Console.Write($"进度: {report.ProgressPercentage:F2}% | ");
                Console.Write($"已传输: {FormatFileSize(report.BytesRead)} / {FormatFileSize(report.TotalBytes)} | ");
                Console.Write($"速度: {FormatFileSize((long)report.Speed)}/s");
                Console.WriteLine();
            });

            var sender = new FileSender();

            try
            {
                var success = await sender.SendFileAsync(filePath, serverUrl, progress);

                if (success)
                {
                    Console.WriteLine("\n文件传输完成!");
                }
                else
                {
                    Console.WriteLine("\n文件传输失败!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n传输过程中发生错误: {ex.Message}");
            }

            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }

        static string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            int order = 0;
            double len = bytes;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }
    }


    class FileSender
    {
        private readonly HttpClient _httpClient;

        public FileSender()
        {
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromHours(2) // 2小时超时
            };
        }

        public async Task<bool> SendFileAsync(string filePath, string serverUrl,
            IProgress<UploadProgress> progress = null)
        {
            if (!File.Exists(filePath))
            {
                Console.WriteLine($"文件不存在: {filePath}");
                return false;
            }

            var fileInfo = new FileInfo(filePath);
            var fileName = Path.GetFileName(filePath);

            Console.WriteLine($"开始上传文件: {fileName}");
            Console.WriteLine($"文件大小: {FormatFileSize(fileInfo.Length)}");

            try
            {
                await using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    var content = new ProgressStreamContent(fileStream, progress, fileName);

                    var response = await _httpClient.PostAsync(serverUrl, content);

                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsStringAsync();
                        Console.WriteLine($"上传成功: {result}");
                        return true;
                    }
                    else
                    {
                        Console.WriteLine($"上传失败: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}");
                        return false;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"上传过程中出错: {ex.Message}");
                return false;
            }
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            int order = 0;
            double len = bytes;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }
    }

    public class UploadProgress
    {
        public long BytesRead { get; set; }
        public long TotalBytes { get; set; }
        public double ProgressPercentage => TotalBytes > 0 ? (BytesRead * 100.0) / TotalBytes : 0;
        public double Speed { get; set; } // bytes per second
    }

    class ProgressStreamContent : StreamContent
    {
        private readonly Stream _stream;
        private readonly IProgress<UploadProgress> _progress;
        private readonly string _fileName;
        private readonly long _totalBytes;
        private long _bytesRead;
        private readonly System.Diagnostics.Stopwatch _stopwatch;

        public ProgressStreamContent(Stream stream, IProgress<UploadProgress> progress, string fileName)
            : base(stream)
        {
            _stream = stream;
            _progress = progress;
            _fileName = fileName;
            _totalBytes = stream.Length;
            _bytesRead = 0;
            _stopwatch = System.Diagnostics.Stopwatch.StartNew();
        }

        protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            var buffer = new byte[81920]; // 80KB buffer
            int read;

            while ((read = await _stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await stream.WriteAsync(buffer, 0, read);
                _bytesRead += read;

                // 计算速度
                var elapsedSeconds = _stopwatch.Elapsed.TotalSeconds;
                var speed = elapsedSeconds > 0 ? _bytesRead / elapsedSeconds : 0;

                _progress?.Report(new UploadProgress
                {
                    BytesRead = _bytesRead,
                    TotalBytes = _totalBytes,
                    Speed = speed
                });
            }
        }

        protected override bool TryComputeLength(out long length)
        {
            length = _totalBytes;
            return true;
        }
    }
}


//receiver
using System.Net;
using System.Text;

namespace ConsoleApp14
{

    class Program
    {
        static async Task Main(string[] args)
        {
            // 设置控制台输出编码为 UTF-8
            Console.OutputEncoding = Encoding.UTF8;
            // 设置控制台输入编码为 UTF-8
            Console.InputEncoding = Encoding.UTF8;
            Console.WriteLine("=== 大文件接收端 (ConsoleB) ===");

            // 配置
            string url = "http://localhost:8080/upload/";
            string saveDirectory = @"E:\";

            var receiver = new FileReceiver(url, saveDirectory);

            // 设置 Ctrl+C 处理
            Console.CancelKeyPress += (sender, e) =>
            {
                e.Cancel = true;
                Console.WriteLine("正在停止服务...");
                receiver.Stop();
                Environment.Exit(0);
            };

            try
            {
                await receiver.StartAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"服务运行错误: {ex.Message}");
            }

            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }
    }

    class FileReceiver
    {
        private readonly HttpListener _listener;
        private readonly string _saveDirectory;

        public FileReceiver(string prefix, string saveDirectory)
        {
            _listener = new HttpListener();
            _listener.Prefixes.Add(prefix);
            _saveDirectory = saveDirectory;
            Directory.CreateDirectory(saveDirectory);
        }

        public async Task StartAsync()
        {
            _listener.Start();
            Console.WriteLine("文件接收服务已启动...");
            Console.WriteLine("等待文件上传...");

            while (true)
            {
                try
                {
                    var context = await _listener.GetContextAsync();
                    _ = Task.Run(() => ProcessRequestAsync(context));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"接收错误: {ex.Message}");
                }
            }
        }

        private async Task ProcessRequestAsync(HttpListenerContext context)
        {
            var request = context.Request;
            var response = context.Response;

            try
            {
                if (request.HttpMethod == "POST")
                {
                    // 获取文件名
                    var fileName = request.Headers["X-FileName"] ?? "unknown_file.dat";
                    var filePath = Path.Combine(_saveDirectory, fileName);

                    Console.WriteLine($"开始接收文件: {fileName}");
                    var stopwatch = System.Diagnostics.Stopwatch.StartNew();

                    // 流式接收文件
                    await using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                    {
                        await request.InputStream.CopyToAsync(fileStream);
                    }

                    stopwatch.Stop();
                    var fileInfo = new FileInfo(filePath);
                    Console.WriteLine($"文件接收完成: {fileName}");
                    Console.WriteLine($"文件大小: {FormatFileSize(fileInfo.Length)}");
                    Console.WriteLine($"耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒");
                    Console.WriteLine($"平均速度: {FormatFileSize((long)(fileInfo.Length / stopwatch.Elapsed.TotalSeconds))}/s");

                    // 发送成功响应
                    response.StatusCode = 200;
                    await using (var writer = new StreamWriter(response.OutputStream))
                    {
                        await writer.WriteAsync("文件上传成功");
                    }
                }
                else
                {
                    response.StatusCode = 405;
                    await using (var writer = new StreamWriter(response.OutputStream))
                    {
                        await writer.WriteAsync("只支持 POST 方法");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理请求时出错: {ex.Message}");
                response.StatusCode = 500;
                await using (var writer = new StreamWriter(response.OutputStream))
                {
                    await writer.WriteAsync($"服务器错误: {ex.Message}");
                }
            }
            finally
            {
                response.Close();
            }
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            int order = 0;
            double len = bytes;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        public void Stop()
        {
            _listener?.Stop();
            _listener?.Close();
        }
    }
}

 

 

//Simple way, copy stream asynchronously

namespace ConsoleApp16
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            string sourcePath = @"E:\test.txt";
            string destPath = @"E:\NewTest.txt";
            await CopyFileAsync(sourcePath, destPath,(int)(new FileInfo(sourcePath).Length));
            Console.WriteLine($"Finished!");
        }


        public static async Task CopyFileAsync(string sourcePath, string destinationPath, int bufferSize = 81920)
        {
            using var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.SequentialScan);
            using var destinationStream = new FileStream(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize, FileOptions.Asynchronous);

            await sourceStream.CopyToAsync(destinationStream, bufferSize);
        }
    }
}

 

 

image

 

posted @ 2025-10-11 14:10  FredGrit  阅读(4)  评论(0)    收藏  举报