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

防止反复造轮子,直接上代码。

客户端代码如下:

csharp 复制代码
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())
                {
                    // 构建上传请求的 Uri
                    string uploadUri = this.textBox2.Text+"/api/File/UploadFolder"; // 替换为你的远程 IIS 服务器地址

                    // 创建 MultipartFormDataContent 用于封装文件内容
                    MultipartFormDataContent content = new MultipartFormDataContent();

                    // 添加压缩后的文件内容到 MultipartFormDataContent
                    byte[] 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代码:

csharp 复制代码
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;
        }
    }
}
csharp 复制代码
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);
                }
            }
        }


      
    }
}

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

过滤器,全局异常捕获:

csharp 复制代码
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中全局注册

csharp 复制代码
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());
        }
    }
}

日志类:

csharp 复制代码
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 MB

        private 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");
                    }
                }
            }
        }

    }
}

工具类:

csharp 复制代码
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;
        }

    }
}
相关推荐
专注VB编程开发20年5 小时前
C#全面超越JAVA,主要还是跨平台用的人少
java·c#·.net·跨平台
一个帅气昵称啊16 小时前
.Net通过EFCore和仓储模式实现统一数据权限管控并且相关权限配置动态生成
.net·efcore·仓储模式
helloworddm18 小时前
CalculateGrainDirectoryPartition
服务器·c#·.net
步步为营DotNet18 小时前
深度剖析.NET中HttpClient的请求重试机制:可靠性提升与实践优化
开发语言·php·.net
ChaITSimpleLove19 小时前
使用 .net10 构建 AI 友好的 RSS 订阅机器人
人工智能·.net·mcp·ai bot·rss bot
专注VB编程开发20年19 小时前
vb.net宿主程序通过统一接口直接调用,命名空间要一致
服务器·前端·.net
ChaITSimpleLove1 天前
基于 .NET Garnet 1.0.91 实现高性能分布式锁(使用 Lua 脚本)
分布式·.net·lua
用户4488466710602 天前
.NET进阶——深入理解线程(2)Thread入门到精通
c#·.net
一个帅气昵称啊2 天前
.Net——AI智能体开发基于 Microsoft Agent Framework 实现第三方聊天历史存储
人工智能·microsoft·.net