C# HTTP 文件上传、下载服务器

程序需要管理员权限,vs需要管理员打开

首次运行需要执行以下命令注册URL(管理员命令行)

bash 复制代码
netsh advfirewall firewall add rule name="FileShare" dir=in action=allow protocol=TCP localport=8000
ipconfig | findstr "IPv4"
csharp 复制代码
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        string path = @"D:\8000"; // 共享目录
        int port = 8000;
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add($"http://+:{port}/");
        listener.Start();
        Console.WriteLine($"服务器已启动: http://{GetLocalIP()}:{port}");

        while (true)
        {
            var context = listener.GetContext();
            if (context.Request.HttpMethod == "POST")
            {
                ProcessUploadRequest(context, path);
            }
            else
            {
                ProcessRequest(context, path);
            }
        }
    }

    static void ProcessUploadRequest(HttpListenerContext context, string rootPath)
    {
        try
        {
            // 获取上传文件名
            string filename = context.Request.Headers["X-FileName"] ?? Path.GetRandomFileName();
            string filePath = Path.Combine(rootPath, filename);

            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                context.Request.InputStream.CopyTo(fs);
            }

            SendResponse(context, HttpStatusCode.Created, "文件上传成功");
        }
        catch (Exception ex)
        {
            SendResponse(context, HttpStatusCode.InternalServerError, $"上传失败: {ex.Message}");
        }
    }

    static void ProcessRequest(HttpListenerContext context, string rootPath)
    {
        try
        {
            string requestPath = context.Request.Url.LocalPath.TrimStart('/');
            string fullPath = Path.Combine(rootPath, requestPath);

            // 处理文件下载
            if (File.Exists(fullPath))
            {
                using (FileStream fs = File.OpenRead(fullPath))
                {
                    context.Response.ContentType = GetMimeType(Path.GetExtension(fullPath));
                    context.Response.AddHeader("Content-Disposition", $"attachment; filename=\"{Path.GetFileName(fullPath)}\"");
                    fs.CopyTo(context.Response.OutputStream);
                }
            }
            // 处理目录浏览
            else if (Directory.Exists(fullPath))
            {
                string directoryList = GenerateDirectoryListing(fullPath, context.Request.Url.AbsoluteUri);
                byte[] buffer = Encoding.UTF8.GetBytes(directoryList);
                context.Response.ContentType = "text/html; charset=utf-8";
                context.Response.OutputStream.Write(buffer, 0, buffer.Length);
            }
            else
            {
                SendResponse(context, HttpStatusCode.NotFound, "资源不存在");
            }
        }
        catch (Exception ex)
        {
            SendResponse(context, HttpStatusCode.InternalServerError, $"处理请求失败: {ex.Message}");
        }
        finally
        {
            context.Response.Close();
        }
    }

    static string GenerateDirectoryListing(string path, string baseUrl)
    {
        var sb = new StringBuilder();
        sb.Append("<html><head><title>文件列表</title></head><body>");
        sb.Append($"<h1>文件列表 - {path}</h1><ul>");

        // 添加返回上级目录链接
        if (Directory.GetParent(path) != null)
        {
            sb.Append($"<li><a href='{baseUrl}../'>[上级目录]</a></li>");
        }

        // 遍历目录
        foreach (var dir in Directory.GetDirectories(path))
        {
            string dirName = Path.GetFileName(dir);
            sb.Append($"<li><a href='{baseUrl}{dirName}/'>[目录] {dirName}/</a></li>");
        }

        // 遍历文件
        foreach (var file in Directory.GetFiles(path))
        {
            string fileName = Path.GetFileName(file);
            sb.Append($"<li><a href='{baseUrl}{fileName}'>{fileName}</a></li>");
        }

        sb.Append("</ul></body></html>");
        return sb.ToString();
    }

    static void SendResponse(HttpListenerContext context, HttpStatusCode statusCode, string message)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(message);
        context.Response.StatusCode = (int)statusCode;
        context.Response.ContentType = "text/plain; charset=utf-8";
        context.Response.OutputStream.Write(buffer, 0, buffer.Length);
    }

    /***   
    * MIME类型映射类
    * MIME(Multipurpose Internet Mail Extensions)‌ 
    * 类型是一种标准化的方式,用于描述互联网上传输的内容类型(例如文本、图像、视频等)。
    * 它的核心作用是告诉浏览器或客户端‌如何正确处理文件‌(例如直接显示、下载、调用外部程序打开等)
    */
    static string GetMimeType(string extension)
    {
        var mimeTypes = new Dictionary<string, string>
        {
            { ".txt", "text/plain" },
            { ".pdf", "application/pdf" },
            { ".doc", "application/msword" },
            { ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
            { ".xls", "application/vnd.ms-excel" },
            { ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
            { ".png", "image/png" },
            { ".jpg", "image/jpeg" },
            { ".jpeg", "image/jpeg" },
            { ".gif", "image/gif" },
            { ".zip", "application/zip" }
        };
        return mimeTypes.TryGetValue(extension.ToLower(), out string mime) ? mime : "application/octet-stream";
    }

    static string GetLocalIP()
    {
        return Dns.GetHostEntry(Dns.GetHostName())
            .AddressList.First(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            .ToString();
    }
}

文件上传

curl.exe -X POST -H "X-FileName: Git-2.46.2-64-bit.exe" --data-binary "@C:\Users\Ins\Downloads\Git-2.46.2-64-bit.exe" http://192.168.1.242:8000/![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5cee6643652b4d94ad4c8534673b97b1.png)

相关推荐
小杨不想秃头2 小时前
信息安全工程师教程第二章密码学
运维·服务器·密码学
I'mChloe2 小时前
WGCLOUD怎么监控多台服务器?从Server、Agent 部署到监控面板实战
运维·服务器
Android系统攻城狮2 小时前
Linux PipeWire深度解析之pw_init调用流程与实战(八十三)
linux·运维·服务器·音频进阶·pipewire音频进阶
惊鸿醉2 小时前
Unity 实战:用讯飞 WebAPI 做一个“说普通话、播方言“的语音程序
unity·c#·游戏引擎·语音识别
略略略咯咯3 小时前
C#Unity
开发语言·unity·c#
zbyyd4 小时前
Linux 进程管理详解:从概念到实战
linux·运维·服务器
Behavior5 小时前
Unity文字显示带竖线问题
c#·unity3d
云飞云共享云桌面6 小时前
智能装备工厂研发团队如何利用单台服务器承载 10 路 SolidWorks 并发?
运维·服务器·3d·自动化·制造
辻弋2016 小时前
手动关服务会自动重启、组策略家庭版用不了——Windows Update Blocker用“禁用+锁定”双保险,让Win10/11自动更新彻底闭嘴
服务器·人工智能·windows·电脑·开源软件
躺不平的理查德6 小时前
OpenSSL 的异步 TLS 1.3 加密
linux·运维·服务器