向宁 df8f1e4cb7 refactor: rewrite file-system from Go to .NET 10 / ABP modular
- Replace Go (Kratos/Wire/Watermill) implementation with .NET 10 solution
- Add FileSystem.slnx, Directory.Build.props and ABP module structure
- Keep Docker/Jenkins/docker-compose deployment artifacts
- This drops all Go sources (cmd/, internal/, api/proto) in favor of src/
2026-06-14 15:02:59 +08:00
2025-12-18 09:51:13 +08:00
2025-12-19 16:32:20 +08:00

file-system

基于 .NET 10 + ABP + FastEndpoints + MediatR + EF Core 的文件存储微服务,提供文件上传/下载、分片上传、存储桶管理、文件夹/文件元数据管理与分享等能力。底层使用 S3 兼容存储RustFS/MinIO与 PostgreSQL。提供 HTTP + gRPC 双协议

由原 Go/Kratos 版重写而来,功能 1:1 对齐。

功能特性

  • 文件操作上传、下载、删除、列表、预签名预览24h、文本内容预览10MB
  • 分片上传大文件分片上传init / part / complete / abort服务端按 PartNumber 排序)
  • 存储桶管理:创建、列表、删除
  • 文件夹与元数据:树形文件夹、文件元数据、移动、递归 CTE 事务删除 + best-effort S3 清理
  • 分享链接bcrypt 密码保护、过期时间、下载次数限制
  • JWT 鉴权OIDC/JWKS信 SSO 签发的 RS256 JWT
  • 所有权隔离:受保护接口以 JWT sub 为权威所有者,忽略请求体 owner_id
  • 双协议HTTPFastEndpoints+ gRPC原生 proto共享同一套 MediatR CQRS

技术栈

类别 技术
框架 .NET 10、ABP 10.3模块化、FastEndpoints 8.1REPR、MediatR 14CQRS
数据 EF Core 10 + PostgreSQLNpgsql
存储 AWSSDK.S3ForcePathStyle兼容 RustFS/MinIO
鉴权 OIDC AuthorityJWKS 自动发现)
校验 FluentValidation 12管线自动校验
协议 HTTPFastEndpoints+ gRPC原生 proto

架构分层

FileSystem.Api            → FastEndpoints + Middleware + ABP 模块装配 + gRPC 服务
FileSystem.Application    → MediatR CQRS handlers + DTOs + Validators + 领域事件
FileSystem.Infrastructure → EF Core + DbContext + Configurations + AuditInterceptor + S3 存储
FileSystem.Domain         → Entities + Interfaces + Exceptions零外部依赖

依赖:Api → Application → Infrastructure → Domain。ABP 模块 [DependsOn] 链同构 rag-backend。

快速开始

环境要求

  • .NET 10 SDK
  • PostgreSQL含库 file_system
  • S3 兼容存储RustFS / MinIO
  • 可访问的 SSO 服务(用于 JWKS

构建运行

dotnet build
cd src/FileSystem.Infrastructure && dotnet ef migrations add Init --startup-project ../FileSystem.Api
cd src/FileSystem.Api && dotnet run          # HTTP :8080, gRPC :9090

或 Docker

docker compose up -d

服务监听:

  • HTTP: http://localhost:8080
  • gRPC: localhost:9090
  • Swagger: http://localhost:8080/swagger

配置

运行配置在 src/FileSystem.Api/appsettings.json,环境变量用 __ 分隔节覆盖(如 S3__EndpointS3:Endpoint)。

配置项 说明
Kestrel:Endpoints:Http/Grpc HTTP8080, Http1/ gRPC9090, Http2监听地址
Kestrel:Limits:MaxRequestBodySize 请求体上限100 MiB
ConnectionStrings:Default PostgreSQL 连接串
S3:* S3 兼容端点与凭证
Jwt:Authority SSO 地址,框架自动发现 JWKS
Jwt:RequireHttps 是否要求 HTTPS开发期 false

鉴权

  • 受保护接口要求请求头携带 SSO 下发的 Authorization: Bearer <token>RS256
  • 服务从 JWT 的 sub claim 取用户 ID 作为资源所有者;请求体的 owner_id/created_by 字段仅 proto 兼容保留,不作为鉴权依据
  • 公开接口(无需鉴权):GetShareInfoDownloadShare
  • 分享下载在设置了密码时,必须通过 password 字段并经 bcrypt 校验。

API 端点24 个)

HTTP 路径 鉴权 说明
POST /api/files/upload 登录 上传文件multipart≤100MiB
GET /api/files/download 登录 下载对象
GET /api/files/list 登录 分页列对象默认100/上限1000
GET /api/files/preview 登录 24h 预签名预览 URL
GET /api/files/content 登录 文本内容≤10MB
DELETE /api/files/delete 登录 删除对象
POST /api/files/multipart/init 登录 开启分片会话
PUT /api/files/multipart/part 登录 上传单片
POST /api/files/multipart/complete 登录 合并分片
POST /api/files/multipart/abort 登录 取消会话
POST /api/buckets 登录 建桶
GET /api/buckets 登录 列桶
DELETE /api/buckets 登录 删桶
POST /api/folders 登录+sub 建文件夹parent_id 空=根)
GET /api/folders/tree 登录+sub 该用户所有文件夹
GET /api/folders/{id} 登录+sub 文件夹+子项
PUT /api/folders/{id} 登录+sub 重命名
DELETE /api/folders/{id} 登录+sub 递归删 DB 子树 + best-effort 删 S3
POST /api/folders/{folder_id}/files 登录+sub UUID key 上传到 files 桶 + 元数据
POST /api/files/{id}/move 登录+sub 移动文件target 空=根)
POST /api/share 登录+sub 建分享bcrypt 密码/过期/次数)
DELETE /api/share/{id} 登录+sub 按 id+owner 删
GET /api/share/{token} 公开 查分享信息
POST /api/share/{token}/download 公开 校验密码/过期/次数 → 15min 预签名 URL

gRPC 方法同上,契约见 src/FileSystem.Api/Protos/file.proto

错误码

错误 HTTP 含义
Unauthorized 401 缺少/无效 JWT
Forbidden 403 无权访问他人资源
InvalidParameter 400 参数校验失败
NotFound 404 资源不存在
AlreadyExists 409 资源已存在
ShareExpired 410 分享已过期
ShareExhausted 410 分享下载次数耗尽
SharePassword 401 分享密码缺失或错误
TooLarge 413 超过单文件大小上限100MiB
Description
No description provided
Readme 29 MiB
Languages
C# 99.5%
Dockerfile 0.5%