基于 OpenList 的多网盘文件互传与同步备份工具,体验对齐百度网盘 / 阿里云盘桌面客户端。
把 NAS 本地文件与 OpenList 聚合的云盘(豆包 / 阿里 / 百度 / 天翼等)双向传起来: 左右双栏选文件、队列上传、断点续传、完整性校验、失败自动重试、目录比对、 同步备份(增量扫描 + 服务端复制)。
- 当前版本:2.15.36
- 应用 id:
cloud-sync - 平台:
all(x86 与 ARM 通用,纯 Python,无二进制依赖) - 安装方式:飞牛 应用中心 → 手动安装 → 选择
cloud-sync-<version>.fpk
| 功能 | 说明 |
|---|---|
| OpenList 授权 | 填 OpenList 地址 + 用户名 + 密码(支持 2FA)。密码只用于换 token,应用不存明文,token 失效自动重登;可勾选「记住密码」 |
| 文件对比(双栏) | 左栏本地 / OpenList 目录树、右栏 OpenList 云端目录树。勾选左侧文件/文件夹,一键上传到右侧;两侧可各自切换本地/云端来源 |
| 目录比对 | 左右两栏各选文件夹,点「比对」;差异按仅左侧 / 仅右侧 / 大小不一致分组,每组可全选上传/下载/清除;结果弹窗式展示,支持收起展开 |
| 传输列表 | 上传 + 下载 + OpenList 服务端复制任务同列一表,实时状态(排队中/传输中/成功/失败),分页展示(50/100/200/500 条/页),支持全部暂停/全部取消/清除已结束/全部重试 |
| 断点续传 | 大文件走分片上传,中断后可断点续传;下载流式写入临时文件,校验大小一致后才改名落地 |
| 完整性校验 | 上传完成后回查云端文件大小比对(可关) |
| 失败重试 | 自动重试(指数退避,次数可调);4xx 错误不重试;重试耗尽转失败,可手动重传 |
| 同步备份 | 把 OpenList 源目录绑定到一个或多个云端目标目录,增量扫描后只把缺失文件复制过去;支持自动上传、冲突策略(跳过/覆盖/中止)、文件夹视图(未上传数量角标 + 一键上传) |
| 自动扫描 | 每隔 N 天(默认 7 天,可配置 1-30)在指定时间点(默认 03:00)执行全量扫描;全局扫描并发限制(默认 2,可配置 1-10),避免挤爆服务器 |
| 扫描进度可视化 | 扫描时显示当前阶段(源目录/目标目录/比对)、已扫描文件数、排队状态;扫描完成后显示统计概览(总数/缺失/不一致/已同步) |
| 应用内日志 | 设置页可查看运行日志,支持按级别筛选(全部/仅警告/仅错误),可清空;自动过滤自身请求日志,避免刷屏 |
| 卸载向导 | 卸载时可选择「保留配置」或「清除全部数据」 |
设计原则:只新增,绝不自动删除云端或本地已有文件。「清除」只在用户显式点下并二次确认后才执行,每次删除写入本地审计日志。
- 下载
cloud-sync-<version>.fpk。 - 飞牛 应用中心 → 手动安装 → 上传该文件(已装旧版的直接覆盖升级)。
- 安装依赖
python312(manifest 里已声明,应用中心会自动装)。 - 装好后桌面上出现「云端互传」图标。
统一网关模式(micro_app)要求 fnOS ≥ 1.2.0401。
应用要读 /vol1/1000/... 这类用户目录,而飞牛的用户目录默认互相不可读,不以 root 运行就看不到别的用户的数据。本地目录浏览做了严格白名单限制,越权请求一律拒绝。
- 点「连接」按钮(首次打开会自动弹出)。
- 填三项:
- OpenList 地址:如
http://192.168.0.10:5244; - 用户名 / 密码:OpenList 的管理员或有上传权限的账号;
- 两步验证:开了 2FA 才需要填。
- OpenList 地址:如
- 勾选「记住密码」可避免每次重新输入。
- 点「登录并连接」。
密码不会明文落盘。应用只保存密码的 StaticHash(与 OpenList 服务端一致的算法)和登录换来的 token;token 失效时用 StaticHash 自动重登。
- 左栏浏览目录(可切换本地/云端来源),右栏浏览云端目录;
- 勾选要传输的文件/文件夹,点中间 「上传 →」(两步确认)进入传输列表;
- 点 「比对 ⇄」 对两栏选中的目录做双向比对,结果在下方弹窗展示;
- 比对结果按「仅左侧 / 仅右侧 / 大小不一致」分组,每组可全选操作;
- 上传走 OpenList 服务端复制(云端↔云端)或本地上传队列(本地→云端),不额外占用链路带宽。
- 所有任务(上传/下载/OpenList 复制)同列一表,按状态排序:传输中 > 失败 > 排队中 > 已完成;
- OpenList 复制任务显示「复制中…」无限循环动画(OpenList 不返回真实进度百分比);
- 支持分页、筛选、全部暂停/恢复、全部取消、清除已结束、全部重试;
- 任务状态直接引用 OpenList 服务端任务,不自己探测成功/失败。
- 新建同步:选择 OpenList 源目录 + 一个或多个云端目标目录;
- 冲突策略:跳过已存在(默认)/ 覆盖 / 中止;
- 自动上传:扫描完成后自动把缺失文件提交到 OpenList 复制;
- 文件夹视图:按文件夹分组展示待上传文件,每个文件夹显示未上传数量角标,支持一键上传;
- 文件视图:平铺展示所有待上传文件,支持逐文件上传;
- 扫描进度实时显示,排队中的绑定显示「等待扫描槽位」。
| 项 | 默认 | 说明 |
|---|---|---|
| 同时上传数 | 2 | 并发任务数,1-8 |
| 失败重试次数 | 3 | 指数退避 2s/4s/8s… |
| 上传完成后校验 | 开 | 回查云端大小比对 |
| 自动扫描 | 关 | 开启后每隔 N 天在指定时间点全量扫描 |
| 扫描间隔(天) | 7 | 1-30 天 |
| 扫描时间 | 03:00 | 执行时间点 |
| 全局扫描并发 | 2 | 同时扫描的绑定数,1-10 |
| 文件对比默认路径 | — | 左侧本地/云端、右侧云端的默认起始路径 |
| 排除规则 | *.tmp 等 |
逗号分隔,支持 * 通配 |
| 位置 | 内容 |
|---|---|
| 应用界面 →「设置」→ 查看运行日志 | 最近的运行日志,可按级别筛选 |
| 连接面板 →「测试连接」 | 分步自检(网络 / 登录 / 列目录) |
| 现象 | 多半是 |
|---|---|
| 页面能打开但数据全空 | 接口地址没探测对,强刷一次 |
| 登录报 401 | 用户名或密码错 |
| 登录报 429 | 失败次数过多被锁 5 分钟 |
| 上传一直失败 | 看任务里的错误详情 |
| 大文件传到一半失败 | 属正常断流,点「重传」会从断点续传 |
| OpenList 复制任务一直显示「复制中」 | OpenList 不返回进度百分比,属正常;去 OpenList 任务列表看真实进度 |
| 同步备份扫描很慢 | 目录文件多;可调大扫描并发,但注意不要挤爆 OpenList 服务器 |
cloud-sync/
├── manifest 飞牛应用描述(版本、依赖、入口)
├── config/ privilege(run-as: root)、resource
├── cmd/ 生命周期脚本(必须 LF、必须可执行位)
├── app/
│ ├── ui/ 桌面入口 config 与图标
│ ├── www/index.html 前端(单文件,无构建步骤)
│ └── server/ 后端(纯 Python 标准库)
│ ├── main.py 入口 + 网关 Socket
│ ├── http_api.py HTTP 接口 + AppContext(RLock 单例)
│ ├── openlist.py OpenList API 客户端(所有网络调用收敛于此)
│ ├── upload_queue.py 持久化上传队列(自动重试 / 断点续传)
│ ├── download_queue.py 下载队列(Range 续传 / 大小校验)
│ ├── bindings.py 同步备份(扫描 / 提交 / 自动扫描定时器)
│ ├── httpclient.py HTTP 传输(urllib + curl 降级)
│ ├── hasher.py SHA-256 / StaticHash
│ ├── verify.py 目录比对
│ └── config.py 配置与 settings 覆盖
├── docs/ 设计文档、API 参考、历史说明
├── tests/ 单元测试 + 端到端冒烟
├── tools/ 打包脚本、图标生成
└── wizard/uninstall 卸载向导(保留配置 / 清除数据)
python tests/run_all.py # 一次跑完所有单元测试
python tests/smoke_e2e.py # 端到端冒烟(真起 HTTP 服务 + 假 OpenList)
node tests/test_ui.js # 前端测试(jsdom)python tools/build_fpk.py --project .打包脚本含 52 项自检:必需文件、JSON 合法性、cmd 脚本换行/BOM、图标尺寸、 入口 key 与网关前缀一致性、Python 语法编译等。
MIT。开发者 / 发布者:ffvz。
OpenList 的接口契约来自服务端源码逐文件核对,见
docs/API参考.md。 本应用的所有网络调用都收敛在app/server/openlist.py一个文件里。