防止反复造轮子,直接上代码。
客户端代码如下:
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;}}
}