当前位置: 首页 > 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.zskr.cn/news/18781.html

相关文章:

  • 2、python get请求
  • 可解释AI技术解析与模型监控实践
  • 开源多场景问答社区论坛Apache Answer本地部署并发布至公网使用 - 实践
  • 2025异型钢厂家最新推荐榜:定制化生产与卓越品质引领者
  • 2025热喷铝厂家最新推荐榜:品质卓越与专业服务的行业首选!
  • 2025方钢厂家,异型钢厂家,六角钢厂家最新推荐榜:品质与性价比兼备的首选品牌!
  • QuickLook软件!一款鼠标单击PDF即能显示内容的软件!
  • iOS 26 崩溃日志深度指南,如何收集、符号化、定位与监控 - 实践
  • 2020CSP-J2比赛记录题解
  • 让博客园设置支持PlantUml画图
  • 光谱相机的未来趋势 - 详解
  • Hall定理学习笔记
  • 面向对象抽象,接口多态综合-动物模拟系统
  • 个人微信开发文档
  • 象棋图片转FEN字符串详细教程
  • 详细介绍:正点原子【第四期】Linux之驱动开发学习笔记-6.1 pinctrl和gpio子系统
  • 深入解析:可持续金融的新范式:拆解欧盟ESG监管体系及其全球影响力
  • 2023 CCPC final G
  • 八字手链人物传记计划——旭
  • 详细介绍:c# datagridview添加list内容
  • MATLAB复杂曲线曲面造型及导函数实现
  • 达梦使用jemalloc内存分配器
  • 基于Python的FastAPI后端开发框架如何使用PyInstaller 进行打包与部署
  • 2025 年气体/实验室/调压/气路/减压阀厂家推荐榜:聚焦安全与专业,助力各行业精准选品
  • 摸鱼混子回归 - ZERO
  • 2025 年国内润滑油厂商最新推荐榜:聚焦优质品牌实力,助力企业精准选品润滑油净化/过滤/回用/液压油润滑油过滤厂商推荐
  • 基于形态学的权重自适应图像去噪的MATLAB实现
  • 2025 年油水分离器 / 气液分离器 / 液固分离器 / 水分离器 / 油分离器厂家推荐:西安同大技术沉淀与流体净化解决方案解析
  • OOP-实验1
  • 哪款剪贴板增强软件最好用?有什么剪贴板内容大全值得分享?多款剪切板历史免费版管理工具推荐