数据文件 FTP 自动上传程序:按配置规则把本地"年月 / 年月日"目录组织的数据文件,自动上传到一台或多台标准 FTP 服务器。Windows 常驻服务程序,无 GUI,低资源占用,支持崩溃重启自动补传。
- 多数据源、多规则:一条规则对应一个数据源,规则可独立启停
- 文件名占位符解析:
{station}/{yyyyMM}/{yyyyMMdd}/{yyyyMMddHH}/{yyyyMMddHHmm}/{yyyyMMddHHmmss}(遵循 C# 时间格式规范) - 远端目录三种模式:固定目录 / 固定目录 + 动态子目录模板 / 保留
source_root相对目录结构(flatten_subdirs可平铺) - 写入保护:正在写入的文件不会被上传(大小/修改时间稳定后才入队)
- 失败自动重试:指数退避、单轮上限后交还扫描重试;多服务器独立状态、互不阻塞
- FTP 连接复用:每 worker 一个连接池,跨文件复用连接(避免每文件一次连接+登录)
- 崩溃重启补传:已上传记录持久化 SQLite,重启自动补传遗漏文件
- 本地处置:保留(keep) / 删除(delete) / 归档(archive) + 保留天数清理
- 运行日志与上传日志(CSV)分开、按天滚动、超期自动清理
- 运行状态:
status.json定期生成(含今日上传/失败、待传数、运行时长),--status可读查看 - 运维命令:
--check-config/--test-ftp/--status/--force-reupload - Windows x86 / x64 双架构发布,单实例运行,优雅退出
完整用户使用手册见随发布分发的 readme.txt。
- .NET 10(
net10.0,非 Windows-targeted,macOS 可交叉构建) - FluentFTP 54(标准 FTP,明文 21 端口;不支持 FTPS/SFTP)
- Tomlyn(TOML 解析)
- Microsoft.Data.Sqlite(上传记录持久化)
- Microsoft.Extensions.Hosting(服务/控制台双模式)
FileRelay.slnx
├── src/FileRelay/
│ ├── Common/ # PathResolver(路径按 exe 同目录解析)、AppDirs
│ ├── Configuration/ # TOML 加载/合并/校验、TimeSpec、自动生成最小配置
│ ├── Matching/ # 文件名占位符→正则、目录模板展开、路径清洗
│ ├── Scanner/ # 扫描主循环、候选评估、稳定性状态机
│ ├── Upload/ # 上传队列/Worker/Service、连接池、重试状态机、远端路径组装
│ ├── Store/ # SQLite 记录库 + 内存缓存、路径规范化
│ ├── LocalFile/ # 本地处置(keep/delete/archive)与保留期清理
│ ├── Logging/ # 运行日志、上传 CSV 日志、按天滚动与清理
│ ├── Status/ # status.json 生成(源生成序列化,trim 兼容)
│ ├── Hosting/ # 入口、命令行参数、单实例、Worker 组合根
│ ├── Assets/ # Windows 程序图标(FileRelay.ico)
│ └── Deploy/ # 随发布分发的打包资源:config.example.toml、readme.txt、install/uninstall.bat
├── tests/FileRelay.Tests/ # xUnit 单测 + 集成测试(pyftpdlib 本地 FTP)
└── docs/ # 01-PRD.md / 02-SDD.md / 03-DDD.md
dotnet build FileRelay.slnx
dotnet test tests/FileRelay.Tests集成测试需要本地 FTP 服务器(pyftpdlib 2.x):仓库自带 .venv,或通过环境变量 FILERELAY_FTP_PYTHON 指定可用 python;无法启动时相关测试跳过。
在 Windows 环境执行仓库根目录的 publish.bat,一键构建 x86/x64 并合并到 publish/ 目录:
publish/
├── FileRelay-x64.exe # 64 位(自包含单文件,原生库已内嵌)
├── FileRelay-x86.exe # 32 位(自包含单文件,原生库已内嵌)
├── config.example.toml # 共享
├── readme.txt # 共享
├── install.bat # 按系统架构自动选择对应 exe 注册服务
└── uninstall.bat
等价的手动命令:
dotnet publish src/FileRelay -c Release -r win-x64 --self-contained true# 64 位
rm -f publish/FileRelay-x64.exe && cp src/FileRelay/bin/Release/net10.0/win-x64/FileRelay.exe publish/FileRelay-x64.exe- 原生库(
e_sqlite3.dll)通过IncludeNativeLibrariesForSelfExtract内嵌进单文件 exe,因此 x86/x64 产物可合并到同一目录互不冲突 - 默认体积优化(csproj 内置,仅 Release + RID 生效):单文件 + 压缩 + 不变全球化 + 原生库内嵌 + IL 裁剪(
publish.bat带-p:PublishTrimmed=true)→ 约 13MB/架构(保留 Tomlyn/FluentFTP 裁剪警告,已在本机裁剪版冒烟实测 TOML 解析/FTP 上传/SQLite/status.json 全链路正常)
扫描线程(定时) → 候选评估(后缀/空文件/mtime/去重/认领) → 稳定性状态机 → 上传队列(有界)
↓ 每日一次记录清理/日志清理
上传 Worker × N(每 worker:连接池 + 重试状态机)→ FluentFTP → 成功写 SQLite 记录 + 上传日志
↓ 全部服务器成功
本地处置(keep / delete / archive)
核心设计点:
- 去重与补传:全局去重键 = 规范化绝对路径;记录库只存"成功"状态,未记录 = 未完成,重启后自然补传
- 重试状态机:每(文件×服务器)独立链,
Attempts/NextAttemptAt/Exhausted持久化于内存字典,单轮max_retries耗尽后交还扫描重新认领 - 连接池:每 worker 一池、每服务器至多一条空闲连接,借用时断开自动重连,失败连接丢弃重建
- 记录清理(
record_retention_days,默认 30):每日清理"源文件已不在监控范围"的超期记录;仍在源目录的文件的记录保留(保证不重复上传)。删除页被 SQLite 复用,db 大小稳定
| 文档 | 说明 |
|---|---|
docs/01-PRD.md | 产品需求文档(功能需求/非功能/边界/验收标准) |
docs/02-SDD.md | 软件概要设计(模块划分/关键决策/接口/部署) |
docs/03-DDD.md | 软件详细设计(类设计/流程伪码/SQL/并发细则/测试用例) |
readme.txt | 用户使用手册(随发布分发) |
config.example.toml | 配置文件示例(字段均标注必填/默认值) |
- 1.1.0:时间占位符原子化(
filename_pattern/remote_dir_template支持yyyy/MM/dd/HH/mm/ss任意组合);配置键更名(file_pattern→filename_pattern、timezone→filename_timezone,旧键提示);规则标识改为id(必填唯一,name降为可选显示名);时区支持(源时区filename_timezone+ 远端目标时区remote_dir_timezone,含UTC±H[:mm]写法);FTP 空闲连接超时回收(ftp_idle_timeout_seconds);新增随发布分发的config-reference.md配置参考文档;P1~P4 评审修复(非法日期回退、连接断开超时上限、时区校验放宽等)。 - 1.0:初始交付。配置校验补强、FTP 连接池复用、P0/P1 缺陷修复(重试状态持久化、处置误删防护、扫描轮异常兜底)、易用性增强(
--check-config/--status/status.json 指标/安装脚本/Windows 图标)、win-x86/x64 双架构、上传记录清理机制。