.net web API的文件传输(上传和下载)客户端winform

news/2024/4/15 14:43:23

防止反复造轮子,直接上代码。
客户端代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace FilesClient
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private async void button1_Click(object sender, EventArgs e){// 创建一个 OpenFileDialog 控件并设置相关属性OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "All Files (*.*)|*.*";openFileDialog.Multiselect = false;需要做c#.net 项目的,有时间并且想赚零花钱的老哥,请加Q群:741058172// 显示文件选择对话框DialogResult dialogResult = openFileDialog.ShowDialog();if (dialogResult == DialogResult.OK){string filePath = openFileDialog.FileName;// 压缩文件string compressedFilePath = CompressFile(filePath);// 创建 HttpClient 对象using (HttpClient client = new HttpClient()){// 构建上传请求的 Uristring uploadUri = this.textBox2.Text+"/api/File/UploadFolder"; // 替换为你的远程 IIS 服务器地址// 创建 MultipartFormDataContent 用于封装文件内容MultipartFormDataContent content = new MultipartFormDataContent();// 添加压缩后的文件内容到 MultipartFormDataContentbyte[] fileBytes = File.ReadAllBytes(compressedFilePath);ByteArrayContent fileContent = new ByteArrayContent(fileBytes);content.Add(fileContent, "file", Path.GetFileName(compressedFilePath));try{// 发送上传请求HttpResponseMessage response = await client.PostAsync(uploadUri, content);// 检查响应状态码if (response.IsSuccessStatusCode){MessageBox.Show("文件上传成功!");}else{MessageBox.Show("文件上传失败!");}}catch (Exception ex){MessageBox.Show("文件上传失败:" + ex.Message);}}// 删除压缩后的临时文件File.Delete(compressedFilePath);}}//采用ZIP压缩算法private string CompressFile(string filePath){string compressedFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".zip");using (FileStream originalFileStream = File.OpenRead(filePath)){using (FileStream compressedFileStream = File.Create(compressedFilePath)){using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress)){originalFileStream.CopyTo(compressionStream);}}}return compressedFilePath;}private string UploadFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Downloads");private async void DownloadFile(string fileName){string apiUrl = this.textBox2.Text+"/api/file/DownloadFile?fileName=" + fileName;// 创建文件夹(如果尚未存在)Directory.CreateDirectory(UploadFolderPath);using (HttpClient client = new HttpClient()){HttpResponseMessage response = await client.GetAsync(apiUrl);if (response.IsSuccessStatusCode){using (FileStream fileStream = new FileStream(Path.Combine(UploadFolderPath, fileName), FileMode.Create, FileAccess.Write, FileShare.None)){await response.Content.CopyToAsync(fileStream);}MessageBox.Show("文件下载完成.");}else{MessageBox.Show("下载失败: " + response.ReasonPhrase);}}}private void button2_Click(object sender, EventArgs e){DownloadFile(this.textBox1.Text+ ".zip");}}
}

服务端API代码:

using FileServices.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;namespace FileServices.Controllers
{public class FileController : ApiController{private string UploadFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFolder");private MediaServer _mediaServer = new MediaServer();[HttpPost]public async Task<IHttpActionResult> UploadFolder(){if (!Request.Content.IsMimeMultipartContent("form-data")){return StatusCode(HttpStatusCode.UnsupportedMediaType);}var provider = new MultipartMemoryStreamProvider();await Request.Content.ReadAsMultipartAsync(provider);await _mediaServer.UploadFolder(provider, UploadFolderPath);// 创建文件夹(如果尚未存在)return Ok();}[HttpGet]public async Task<HttpResponseMessage> DownloadFile(string fileName){// 获取文件路径string filePath = HttpContext.Current.Server.MapPath("~/UploadFolder/" + fileName);// 检查文件是否存在if (!File.Exists(filePath)){return Request.CreateErrorResponse(HttpStatusCode.NotFound, "The specified file does not exist.");}// 创建 HTTP 响应消息HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);// 设置响应内容using (FileStream fileStream = File.OpenRead(filePath)){response.Content = new StreamContent(fileStream);// 设置响应头response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"){FileName = fileName};await response.Content.LoadIntoBufferAsync();}return response;}}
}
using FileServices.Unit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;namespace FileServices.Services
{public class MediaServer {public async Task UploadFolder(MultipartMemoryStreamProvider provider , string _uploadFolder){// 创建文件夹(如果尚未存在)Directory.CreateDirectory(_uploadFolder);foreach (var content in provider.Contents){var disposition = content.Headers.ContentDisposition;var fileName = disposition.FileName.Trim('"');fileName = IOTools.GetFileName(fileName);var fileData = await content.ReadAsByteArrayAsync();// 将文件保存到本地文件夹中var filePath = Path.Combine(_uploadFolder, fileName);using (var fileStream = new FileStream(filePath, FileMode.Create)){await fileStream.WriteAsync(fileData, 0, fileData.Length);}}}}
}

上传下载代码看上面就够了,

过滤器,全局异常捕获:

using FileServices.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Filters;namespace FileServices.Filters
{public class GlobalExceptionHandler : ExceptionFilterAttribute{private static LogServices _logServices = new LogServices();public override void OnException(HttpActionExecutedContext context){// 在这里处理异常,并且返回适当的响应给客户端// 例如,可以记录日志或者返回自定义错误信息// 记录日志LogException(context.Exception);// 返回适当的响应给客户端context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError){Content = new StringContent("An error occurred, please try again later."),ReasonPhrase = "Internal Server Error"};}private void LogException(Exception exception){// 在这里编写将异常信息记录到日志的代码// 可以使用任何你喜欢的日志库或者自己实现记录日志的逻辑Task.Run(async ()=> {await _logServices.WriteErrorLog(exception.ToString());}).Wait();}}
}

Global中全局注册

using FileServices.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;namespace FileServices
{public class WebApiApplication : System.Web.HttpApplication{protected void Application_Start(){AreaRegistration.RegisterAllAreas();GlobalConfiguration.Configure(WebApiConfig.Register);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);// 注册全局异常过滤器GlobalConfiguration.Configuration.Filters.Add(new GlobalExceptionHandler());}}
}

日志类:

using FileServices.Unit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;namespace FileServices.Services
{public class LogServices{public string LogDirectory { get; set; }public string TimeDirName { get; set; }private string LogFileName { get; set; }private const long maxLogSize = 2 * 1024 * 1024; // 2 MBprivate string FirstLogFileName { get; set; }private string newFileName { get; set; }public LogServices(){//在根目录创建Log文件夹IOTools.CreatLogDir("Log");//初始化LogDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Log");TimeDirName = DateTime.Now.ToString("yyyyMMdd");FirstLogFileName = $"log_{DateTime.Now:yyyyMMddHHmmss}.txt";}public async Task WriteErrorLog(string message){await WriteLog("Error", message);}public async Task WriteInfoLog(string message){await WriteLog("Info", message);}public async Task WriteLog(string logType, string message){//创建文件夹string dirType = TimeDirName + "\\" + logType;IOTools.CreatDir(dirType, LogDirectory);LogFileName = Path.Combine(LogDirectory, dirType, FirstLogFileName);if (!File.Exists(LogFileName)){using (StreamWriter sw = File.CreateText(LogFileName)){await sw.WriteLineAsync($"【{logType}{DateTime.Now} \r\n {message}  \r\n \r\n");}}else{FileInfo fileInfo = new FileInfo(LogFileName);if (fileInfo.Length > maxLogSize){string newFileName = $"log_{DateTime.Now:yyyyMMddHHmmss}.txt";FirstLogFileName = newFileName;LogFileName = Path.Combine(LogDirectory, dirType, newFileName);using (StreamWriter sw = File.CreateText(LogFileName)){await sw.WriteLineAsync($"【{logType}{DateTime.Now} \r\n {message}  \r\n \r\n");}}else{using (StreamWriter sw = File.AppendText(LogFileName)){await sw.WriteLineAsync($"【{logType}{DateTime.Now} \r\n {message}  \r\n \r\n");}}}}}
}

工具类:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;namespace FileServices.Unit
{public class IOTools{public static void CreatLogDir(string name){string rootDirectory = Directory.GetCurrentDirectory();CreatDir(name, rootDirectory);}public static void CreatDir(string name, string path){if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");string logPath = Path.Combine(path, name);// 判断文件夹是否存在if (!Directory.Exists(logPath)){// 在当前项目根目录创建一个新的文件夹Directory.CreateDirectory(logPath);}}public static string GetFileName(string fileName){fileName = fileName.Trim('"');// 如果 fileName 为空,则可以根据需要生成唯一的文件名if (string.IsNullOrEmpty(fileName)){fileName = Guid.NewGuid().ToString();}return fileName;}}
}

http://www.ppmy.cn/news/1274064.html

相关文章

飞天使-docker知识点8-docker的资源限制

文章目录 容器资源限制示例OOM 优先级机制内存限制参数swap 限制 容器资源限制 Docker提供了多种资源限制的方式&#xff0c;可以根据应用程序的需求和系统资源的可用性进行选择。以下是一些常见的Docker资源限制及其使用情况&#xff1a;CPU限制&#xff1a;通过设置CPU的配额…

飞天使-docker知识点6-容器dockerfile各项名词解释

文章目录 docker的小技巧dockerfile容器为什么会出现启动了不暂停查看docker 网桥相关信息 docker 数据卷 docker的小技巧 [rootlight-test playbook-vars[]# docker inspect -f "{{.NetworkSettings.IPAddress}}" d3a9ae03ae5f 172.17.0.4docker d3a9ae03ae5f:/etc…

【Leetcode】计算器

思路 用栈来完成&#xff1b; 考虑到运算关系&#xff0c;先乘除后加减&#xff1b;此外&#xff0c;一般计算式首个数字式正数&#xff1b;判断字符是否为数字&#xff0c;str.isdigit()字符转数字&#xff1a;ord(str) - ord(‘0’)遇到加减符&#xff0c;压栈数字&#xf…

WEB渗透—PHP反序列化(四)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

MQ入门—centos 7安装RabbitMQ 安装

三&#xff1a;RabbitMQ 安装 1.环境准备 Linux 的 CentOS 7.x 版本。Xftp 传输安装包到 Linux。Xshell 连接 Linux&#xff0c;进行解压安装。 RabbitMQ安装包 链接&#xff1a;https://pan.baidu.com/s/1ZYVI4YZlvMrj458jakla9A 提取码&#xff1a;dyto xshell安装包 链接&…

猫粮哪个牌子好又安全?好又安全的主食冻干猫粮牌子推荐

现在越来越多的铲屎官关注猫咪的食品选择&#xff0c;而冻干猫粮一直是热门话题。其中主食冻干的肉含量很高&#xff0c;富含猫咪成长所需的蛋白质、维生素等营养物质。而且冻干工艺还保留了食材的原始风味&#xff0c;复水后可以恢复鲜肉的口感&#xff0c;猫咪很喜欢吃&#…

基于主动安全的AIGC数据安全建设

面对AIGC带来的数据安全新问题&#xff0c;是不是就应该一刀切禁止AIGC的研究利用呢&#xff1f;答案是否定的。要发展AIGC&#xff0c;也要主动积极地对AIGC的数据安全进行建设。让AIGC更加安全、可靠的为用户服务。为达到此目的&#xff0c;应该从三个方面来开展AIGC的数据安…

智能优化算法应用:基于模拟退火算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于模拟退火算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于模拟退火算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.模拟退火算法4.实验参数设定5.算法结果6.…

低代码赋能,解锁汽车行业数字化转型时代下的“新机遇”!

“数字化转型”已经成为现代企业不可忽视的重要话题。虽然不同的企业&#xff0c;转型的方式和效果各有不同&#xff0c;但如果我们从更高的层面去审视&#xff0c;会发现数字化转型的核心其实就是利用云计算、大数据、人工智能、物联网、区块链等数字化技术和能力&#xff0c;…

LAMP平台——构建PHP运行环境

在构建LAMP平台时&#xff0c;各组件的安装顺序依次为Linux、Apache、MySQL、PHP。其中Apache和 MySQL的安装并没有严格的顺序&#xff1b;而PHP环境的安装一般放到最后&#xff0c;负责沟通Web服务器和数据库 系统以协同工作。 PHP 即 Hypertext Preprocessor&#xff08;超级…

查询某个类是在哪个JAR的什么版本开始出现的方法

背景 我们在依赖第三方JAR时&#xff0c;同时也会间接的依赖第三方JAR引用的依赖&#xff0c;而当我们项目中某个依赖的版本与第三方JAR依赖的版本不一致时&#xff0c;可能会导致第三方JAR的在运行时无法找到某些方法或类&#xff0c;从而无法正常使用。 如我正在开发的一个…

苹果个人开发者如何实现应用下载安装

作为苹果个人开发者&#xff0c;你可以为iOS设备用户提供应用程序&#xff0c;而用户将能够通过下载和安装这些应用来丰富他们的设备体验。本文将详细介绍个人开发者实现应用下载安装的步骤&#xff0c;包括开发和上架应用程序到App Store。 图片来源&#xff1a;苹果个人开发者…

The Grid – Responsive WordPress Grid响应式网格插件

点击阅读The Grid – Responsive WordPress Grid响应式网格插件原文 The Grid – Responsive WordPress Grid响应式网格插件是一个高级 wordpress 网格插件&#xff0c;它允许您在完全可定制且响应迅速的网格系统中展示任何自定义帖子类型。 Grid WordPress 非常适合展示您的博…

C++设计模式之——外观模式

外观模式 概念使用场景示例示例代码运行结果 总结 概念 外观模式是一种结构型设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性&#xff0c;使客户端可以更容易地使用子系统。 使用场景 外观模式的使用场景…

K8S(十)—容器探针

这里写目录标题 容器探针&#xff08;probe&#xff09;检查机制探测结果探测类型何时该使用存活态探针?何时该使用就绪态探针?何时该使用启动探针&#xff1f; 使用exechttptcpgrpc使用命名端口 使用启动探针保护慢启动容器定义就绪探针配置探针HTTP 探测TCP 探测探针层面的…

中国移动公网IP申请过程

一、动机 由于从事互联网行业10年&#xff0c;一直从事移动端&#xff08;前端&#xff09;开发工作&#xff0c;未曾深入了解过后端技术&#xff0c;以至于工作10年也不算进入互联网的门。 所以准备在自己家用设备上搭建各种场景的服务器&#xff08;云服务对个人来说成本偏…

mysql怎么优化查询?

从多个维度优化&#xff0c;这里的优化维度有四个&#xff1a;硬件配置、参数配置、表结构设计和SQL语句及索引。 其中 SQL 语句相关的优化手段是最为重要的。 一、硬件配置 硬件方面的优化可以有 **对磁盘进行扩容、将机械硬盘换为SSD&#xff0c;或是把CPU的核数往上提升一些…

Pytorch读写张量文件

目录 一、加载和保存张量 1、直接读写张量 2、读写张量列表 3、读写张量字典 二、加载和保存模型参数 一、加载和保存张量 1、直接读写张量 对于单个张量&#xff0c;我们可以直接调用load和save函数分别读写它们。这两个函数都要求我们提供一个名称&#xff0c;save要求将…

C++——STL标准模板库——容器详解——string

一、基本概念 string本质是一个类&#xff0c;封装了c风格字符串&#xff08;以\0结尾的字符数组&#xff09;&#xff0c;具备自动管理内存功能&#xff0c;提供了多种构造函数和多种删查增改的成员方法。string的本质特点归结以下几点&#xff1a; 1、动态数组&#xff1a;…

【网络安全技术】传输层安全——SSL/TLS

一、TLS位置及架构 TLS建立在传输层TCP/UDP之上&#xff0c;应用层之下。 所以这可以解决一个问题&#xff0c;那就是为什么抓不到HTTP和SMTP包&#xff0c;因为这两个在TLS之上&#xff0c;消息封上应用层的头&#xff0c;下到TLS层&#xff0c;TLS层对上层消息整个做了加密&…
最新文章