file-system/README.md
向宁 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

5.8 KiB
Raw Blame History

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