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(); } }
//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); } } }