对话笔记直发:7.23 白嫖云盘cftc,tgState,tgNetDisc。分类:网络基建。
三个项目的源码级分析与对比
分析时间:2026-07-22
核查的是三个仓库默认分支当前版本:
我不仅看了 README,也检查了核心源码、部署文件、GitHub Actions、提交历史、开放 Issue,并做了基础构建验证。
一、先说结论
这三个项目实际上可以分为两类:
1. tgState 与 tgNetDisc:同一套核心程序
tgNetDisc 不是另一套独立架构,而是基于 tgState 修改、重新包装后的版本。
tgNetDisc 的 README 也明确写了原项目来自 tgState:
我对两个项目默认分支的全部 Go 源码做了字符级比对,相似度约 97%。两者的:
- 上传接口
- Telegram 存储方式
/d/<file_id>下载协议- 大文件分片格式
- Web 页面结构
- 密码中间件
- Telegram Bot 的
get处理
基本都来自同一套代码。
它们的区别主要是:
tgNetDisc的 Docker 打包更方便- 环境变量名称不同
- 分片大小从 10 MiB 改成 20 MiB
- UI 和域名/子路径适配做了少量调整
- 多架构镜像支持更丰富
因此,这两个项目之间的选择,本质上是:
选原版、许可证更清晰的 tgState,还是选部署体验更好的 tgNetDisc。
2. cftc:完全不同的 Cloudflare 文件管理平台
cftc 不是简单的 Telegram 外链代理,而是一套:
- Cloudflare Workers/Pages 运行时
- D1 元数据数据库
- R2 或 Telegram 双存储
- Web 管理后台
- Telegram Bot 菜单
- 分类、搜索、删除、重命名
- 自定义直链
组成的文件管理系统。
功能明显比前两个多,但代码复杂度、安全风险、状态管理成本也高很多。
二、核心架构差异
tgState / tgNetDisc 的数据流
浏览器 / API
│
▼
Go 服务
│ sendDocument
▼
Telegram Bot API
│
▼
频道 / 群组 / 私聊
│
└── 返回 Telegram file_id
│
▼
/d/<file_id> 外链
下载时:
用户访问 /d/<file_id>
│
▼
Go 服务调用 getFile
│
▼
Telegram CDN 临时地址
│
▼
Go 服务代理数据给用户
特点:
- 不需要数据库
- 文件链接中直接携带 Telegram
file_id - 服务本身几乎无状态
- Telegram 频道可充当人工文件列表
- 所有下载流量都经过自己的 Go 服务
大文件上传时,由浏览器切成多个小文件,最后再上传一个 fileAll.txt 清单:
tgstate-blob
原始文件名
size原始大小
分片1的 file_id
分片2的 file_id
……
下载服务发现这个标记后,再依次从 Telegram 拉取各分片并拼接返回。
cftc 的数据流
浏览器上传 ───────────────┐
│
Telegram Webhook ────────┤
▼
Cloudflare Worker
│ │
│ ├── D1:文件元数据、分类、用户设置
│
├── R2:对象存储
│
└── Telegram:频道/群组存储
访问文件时:
用户访问 /自定义文件名.ext
│
▼
Worker 查询 R2 或 D1
│
├── R2 对象
└── Telegram file_id → Telegram CDN
它比前两个项目多了一层关键状态:
D1 数据库是 cftc 的核心资产。
如果 D1 丢失,即使 Telegram 或 R2 中的文件仍在,自定义链接、分类和后台文件记录也可能全部失效。
三、功能对比表
| 对比项 | tgState | tgNetDisc | cftc |
|---|---|---|---|
| 项目定位 | 极简 Telegram 外链/网盘 | tgState 的部署增强版 | Cloudflare 图床和文件管理平台 |
| 语言 | Go | Go | JavaScript |
| 运行环境 | VPS、Docker、Vercel | VPS、Docker、Vercel | Cloudflare Workers/Pages |
| 文件存储 | Telegram | Telegram | Telegram 或 R2 |
| 元数据数据库 | 无 | 无 | D1,必需 |
| Web 上传 | 支持 | 支持 | 支持 |
| 上传 API | /api,较明确 | /api,较明确 | 有上传端点,但不是稳定、正式文档化 API |
| Telegram 上传 | 发文件后回复 get | 发文件后回复 get | 完整 Bot 菜单和 Webhook |
| Bot 管理面板 | 无 | 无 | 有 |
| 文件列表 | 无,依赖 Telegram 历史 | 无,依赖 Telegram 历史 | 有 |
| 分类管理 | 无 | 无 | 有 |
| 搜索 | 无 | 无 | 有 |
| 批量删除 | 无 | 无 | 有 |
| 自定义链接 | 不支持,使用 file_id | 不支持,使用 file_id | 支持自定义路径名 |
| 大文件分片 | 浏览器端 10 MiB 分片 | 浏览器端 20 MiB 分片 | 不支持分片 |
| 默认单文件限制 | 网页分片绕过 | 网页分片绕过 | 默认 20 MiB,可配置 |
| R2/CDN | 无 | 无 | 支持 |
| 下载 Range/断点续传 | 不支持 | 不支持 | 实现中也没有完整支持 |
| 文件访问密码 | /d/ 文件链接仍是公开的 | /d/ 文件链接仍是公开的 | 文件链接仍是公开的 |
| 部署难度 | 中 | 最低 | 中到高 |
| 多架构镜像 | 主要 amd64/arm64 | 8 种 Linux 架构 | 无此问题 |
| 许可证 | MIT | CC0,但有继承 MIT 的疑问 | MIT |
| 维护成熟度 | 三者中最高,但已停滞 | 中等,核心跟随 tgState | 最年轻、功能多但代码最脆弱 |
四、逐个项目分析
1. tgState
项目定位
tgState 是这条技术路线的原始项目,目标很明确:
用 Telegram Bot API 存储文件,用自己的域名提供外链。
它采用一个小型 Go 服务,没有数据库,没有复杂管理后台。
核心路由只有:
/:上传页面/api:上传 API/pwd:密码页面/d/<file_id>:文件访问
核心代码可以看:
优点
1. 架构非常简单
不需要:
- MySQL
- SQLite
- Redis
- 本地数据目录
- 定期备份应用状态
只要保留:
- Bot Token
- Telegram 频道/群组
- 域名
就能恢复服务。
2. 迁移成本低
由于链接直接保存 Telegram file_id,迁移服务器时不需要搬数据库。
只要:
- 继续使用同一个 Bot
- 保持原域名或配置反向代理
/d/路由保持一致
原有链接大概率可以继续使用。
3. 原文件通常按 Document 上传
Web 上传统一使用 sendDocument,相比 Telegram 的 sendPhoto,更容易保持原始文件内容,不会主动压缩图片。
4. 社区数据最好
截至本次检查:
- Star:约 1045
- Fork:约 182
- 最新 release:
v1.4.1 - 许可证:MIT
在三个项目中,它的用户基础最大。
缺点
1. 没有真正的文件管理后台
系统本身不保存:
- 文件名
- 上传时间
- 分类
- 所属用户
- 删除状态
一旦丢失链接,只能回到 Telegram 频道或聊天记录中寻找文件,再回复 get 获取链接。
2. 下载服务实现不够稳健
下载处理存在几个明显问题:
- 先按
Content-Length分配整个文件大小的内存 - 对普通文件执行一次
Read后再继续复制 - 对不足 12 字节的文件直接执行
buffer[:12],可能触发 panic - 不支持 HTTP Range
- 没有整体请求超时
- 分片获取失败时可能无限重试
- 只接受 Telegram 返回的
application/octet-stream
相关实现见:
这会导致:
- 视频不能正常拖动进度
- 断点续传体验差
- 大文件占用较多 VPS 内存和带宽
- 部分 MP3、MP4、图片类型可能返回 404
- 异常分片可能长期占用连接
开放 Issue 中也能看到“较多 500”“大文件下载”等类似反馈。
3. 密码认证比较薄弱
密码只是保护上传页面和上传接口,不保护 /d/ 文件链接。
另外:
- Cookie 中直接保存明文密码
- Cookie 没有
HttpOnly、Secure、SameSite - 没有会话签名
- 没有 CSRF 保护
- 没有内置限流
- 密码页面使用普通文本输入框
更重要的是,/api?pass=密码 的逻辑有明显错误:
if strings.HasPrefix(r.URL.Path, "/api") &&
r.URL.Query().Get("pass") == conf.Pass {
return
}
密码正确时直接 return,没有调用实际上传处理函数,因此会返回一个空响应。
4. Telegram Bot 功能很少
Bot 只是监听长轮询,并识别回复消息中的 get。
支持识别的类型主要是:
- Document
- Video
- Sticker
对普通 Telegram Photo、Audio 的处理并不完整。
5. 构建链已经很旧
go.mod 声明 Go 1.20,但 release 工作流中实际设置的是 Go 1.17.2,然后临时修改 go.mod:
Go 1.17 和 1.20 现在都已经不适合作为新生产构建基线,应当重新使用受支持版本构建。
2. tgNetDisc
项目定位
tgNetDisc 可以理解为:
tgState核心代码 + 更方便的 Docke