当前位置: 首页 > news >正文

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 bufferint 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;}
}//Receiverclass 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-8Console.OutputEncoding = Encoding.UTF8;// 设置控制台输入编码为 UTF-8Console.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 bufferint 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-8Console.OutputEncoding = Encoding.UTF8;// 设置控制台输入编码为 UTF-8Console.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();}}
}

 

http://www.hskmm.com/?act=detail&tid=28624

相关文章:

  • 2、python get请求
  • 可解释AI技术解析与模型监控实践
  • 人工智能与教育pre
  • 开源多场景问答社区论坛Apache Answer本地部署并发布至公网使用 - 实践
  • 2025 仙桃电梯生产厂家推荐榜单:专注多场景垂直交通解决方案!
  • 2025蒸发式冷气机厂家最新推荐榜:高效制冷与节能优势优质之
  • List之高效安全的 Java 列表深复制工具:ListCopyUtils 的设计与实践
  • AMD、CMD、UMD、ESM和CommonJS
  • 2025异型钢厂家最新推荐榜:定制化生产与卓越品质引领者
  • linux硬盘在线热扩容非LVM情况
  • 【光照】Unity[PBR]环境光中的[漫反射]
  • 2025年六角钢厂家最新推荐榜:品质过硬与性价比之选
  • 2025广东粉末供应厂家TOP10榜单:品质卓越与服务一流的
  • 2025热喷铝厂家最新推荐榜:品质卓越与专业服务的行业首选!
  • 2025方钢厂家,异型钢厂家,六角钢厂家最新推荐榜:品质与性价比兼备的首选品牌!
  • JS单线程设计的目的
  • 强化学习 动作空间(离散/连续)
  • QuickLook软件!一款鼠标单击PDF即能显示内容的软件!
  • Http Security Headers
  • 参照Yalla、Hawa等主流APP核心功能,开发一款受欢迎的海外语聊需要从哪些方面入手
  • 本土化DevOps的突围之路:Gitee如何重塑企业研发效能
  • 隐式类型转化
  • GIT
  • 溶气气浮/浅层气浮/国内知名气浮机靠谱厂家品牌推荐
  • Endnote 使用教程大全!带你快速上手!新手也能用它高效写论文
  • 鸿蒙Next密码自动填充服务:安全与便捷的完美融合 - 实践
  • 覆盖动画 / 工业 / 科研!Rhino 7:专业 3D 建模的全能解决方案,新手也能上手
  • 2020CSP-J2比赛记录题解
  • Binder.getCallingPid()和Binder.getCallingUid()漏洞分析
  • 让博客园设置支持PlantUml画图