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)

相关推荐
Kusunoki_D4 分钟前
速查 Linux 常用指令 II
linux·运维·服务器
jstart千语2 小时前
【消息队列】RabbitMQ基本认识
java·服务器·分布式·rabbitmq
FAREWELL000752 小时前
Unity基础学习(九)输入系统全解析:鼠标、键盘与轴控制
学习·unity·c#·游戏引擎
wanhengidc3 小时前
SCDN能够运用在物联网加速当中吗?
运维·服务器·网络
leona_nuaa3 小时前
p2p虚拟服务器
服务器·网络协议·p2p
wangchen_03 小时前
linux-信号保存和处理
linux·运维·服务器
小白自救计划3 小时前
网络协议分析 实验七 FTP、HTTP、DHCP
网络·网络协议·http
Chandler243 小时前
Go 语言 net/http 包使用:HTTP 服务器、客户端与中间件
服务器·http·golang
z人间防沉迷k4 小时前
互联网协议的多路复用、Linux系统的I/O模式
linux·网络·http
码观天工4 小时前
【.NET必读】RabbitMQ 4.0+重大变更!C#开发者必须掌握的6大升级要点
c#·rabbitmq·.net·mq