ASP.NETCore基于静态文件中间件实现的图床

🚀 基于 ASP.NET Core 静态文件中间件实现的高性能图床系统

在做独立站、AI资源站或者内容分发时,一个稳定、高性能、低成本的图床几乎是刚需。本文将分享一个基于 ASP.NET Core Minimal API + 静态文件中间件实现的轻量级图床方案,支持:

  • ✅ 多文件上传(流式处理,支持大文件)
  • ✅ 多格式链接生成(Markdown / HTML / 原始链接)
  • ✅ 分页文件列表
  • ✅ 文件删除
  • ✅ 存储统计
  • ✅ 高性能 + 无数据库依赖

🧠 设计思路

这个图床的核心理念是:

用文件系统代替数据库,用静态文件中间件代替文件服务接口

核心架构:

1
2
3
4
5
客户端 → 上传接口 → 文件系统 (uploads)

静态文件中间件

/files/xxx 直接访问

⚙️ 核心技术点

1️⃣ 静态文件映射

1
2
3
4
5
6
7
8
9
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(uploadsPath),
RequestPath = "/files",
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=3600");
}
});

👉 作用:

  • /files/xxx.jpg → 直接访问服务器文件
  • 浏览器缓存 1 小时(减少带宽)

2️⃣ 大文件上传优化(重点)

传统方式:

1
上传 → 临时文件 → 再写入目标目录 ❌

你的方案:

1
上传 → 直接流式写入 uploads ✅
1
2
3
4
await using (var fileStream = File.Create(filePath))
{
await section.Body.CopyToAsync(fileStream);
}

👉 优势:

  • ❌ 不占用 temp 目录
  • ❌ 不爆内存
  • ✅ 支持 100MB+ 文件
  • ✅ 性能极高

3️⃣ 文件类型白名单

1
2
3
4
var allowedExtensions = new HashSet<string>
{
".jpg", ".png", ".webp", ...
};

👉 防止:

  • 上传脚本文件(.exe / .js)
  • 安全风险

4️⃣ 多格式链接生成(图床核心)

1
2
3
4
5
6
formats = {
raw: 原始链接
markdown: ![]()
html: <img>
htmlSmall / Medium / Large
}

👉 举例:

1
![image](https://xxx/files/a.png)
1
<img src="https://xxx/files/a.png" width="300" />

👉 这个设计非常关键:

  • 直接适配:

    • 博客
    • Markdown
    • HTML页面
    • 富文本编辑器

5️⃣ 分页查询(避免炸接口)

1
2
.Skip((page - 1) * pageSize)
.Take(pageSize)

返回结构:

1
2
3
4
5
6
{
"files": [],
"total": 100,
"page": 1,
"totalPages": 9
}

👉 优点:

  • 前端无限滚动
  • 控制接口压力

6️⃣ 安全删除(防路径穿越)

1
2
3
var fullPath = Path.GetFullPath(filePath);
if (!fullPath.StartsWith(uploadsFullPath))
return Results.BadRequest("非法路径");

👉 防止攻击:

1
/api/delete/../../windows/system32

7️⃣ 文件统计接口

1
2
3
4
{
count: 文件数量,
totalSize: 总大小
}

👉 用于:

  • 后台面板
  • 存储监控
  • 限额系统(后期可扩展)

🚀 接口一览

上传文件

1
POST /api/upload

支持:

  • 多文件
  • form-data

文件列表

1
GET /api/list?page=1&pageSize=12

删除文件

1
DELETE /api/delete/{fileName}

统计信息

1
GET /api/stats

健康检查

1
GET /api/hello