C# HTTP 文件上传、下载服务器
程序需要管理员权限,vs需要管理员打开
首次运行需要执行以下命令注册URL(管理员命令行)
netsh advfirewall firewall add rule name="FileShare" dir=in action=allow protocol=TCP localport=8000
ipconfig | findstr "IPv4"
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/