a79086e4e8
新增网盘功能 - FileServer 增加 GET /drive/meta|list|download, 每机长期 token 校验 + 目录穿越防护 - 新增 drive.ts 客户端: listDrive / getDriveRoot / downloadDriveFile / collectDriveFiles - ipc 暴露 drive:list|root|download|openFolder|pickDir, DB 增 drive_token 列 + ALTER 迁移 - 新增 DrivePanel.vue, 聊天框加"网盘" tab, 设置页加网盘分区 - 支持整目录递归下载并保持层级 修复远程功能 - 终端: 控制端收到的 output 帧被直接丢弃 (case 'output': return), 导致 xterm 全空白 - ChatServer: ws 构造即 listen, 'listening' 可能早于 start() 挂监听, 导致永久挂起 - USB: serverAttach 自行生成 sessionId 与控制端不一致 (数据帧查表落空); libusb 枚举误用 getDevices() (WebUSB 语义, 只返回已授权设备) 改 loadDevices(); control transfer 传数字 bmRequestType (node-usb v3 要字符串枚举); detachKernelDriver 挪到 selectConfiguration 之前 (否则 EBUSY) - 转发 UI: store 的 onOpened 是 no-op 致对方发起的转发不显示、无轮询致流量/TTL 不刷新、 对方发起的会话关不掉 (新增 closeSession, server 侧关闭需通知对端否则端口泄漏)、 入口/目标补归属标注、方向标签语义统一、监听端口输入框加宽 修复"在线却显示等待重连" - 根因: 启动时主进程先连上对端 (connectTo 早于 createMainWindow), device:wsState 在渲染层订阅前发出去被丢弃; 之后连接一直保持, 再无 open 事件 -> UI 永久停在等待重连 - 改为推全量快照 + 渲染层 mount 时主动拉取 (app:state); 渲染层先注册监听再 await - 通道语义改为 outgoing 或 inbound 任一 WS 活着即可用 (原来只看 outgoing) 修复 Linux 安装后没图标 - linux.icon 指向单张 PNG 时 app-builder 解析不出尺寸 (size=0), 图标被装进 hicolor/0x0/ 非法目录, 桌面环境找不到; 改为指向 resources/icons 目录 (8 个标准尺寸) - StartupWMClass 填的是 productName, 与窗口真实 WM_CLASS (可执行文件名) 对不上, 任务栏找不到启动器; 改为 local-net-msg 其他 - 新增 scripts/selftest 自测框架 (两个虚拟节点 + 真实 ChatServer/ChatClient), 30 条用例全过 - 重写 scripts/make-icon.js 生成多尺寸图标集 (原脚本引用的源图已不存在, sharp 依赖也缺) - 新增 docs/drive.md, docs/connection-status.md
71 lines
3.5 KiB
Markdown
71 lines
3.5 KiB
Markdown
# 网盘 (共享目录浏览 + 选择下载)
|
||
|
||
局域网里两台 LocalNetMsg 互传文件, 以前只能"发消息带附件" (点对点传单个文件)。
|
||
网盘功能让对方能**浏览我机器上指定的共享目录**, 挑需要的文件下载。
|
||
|
||
## 1. 组成
|
||
|
||
```
|
||
被控端 (文件持有方) 控制端 (浏览/下载方)
|
||
┌────────────────────────────┐ ┌──────────────────────────────┐
|
||
│ FileServer (0.0.0.0:47901) │ │ 聊天框 → "网盘" tab │
|
||
│ GET /drive/meta │◀── HTTP ──│ DrivePanel.vue │
|
||
│ GET /drive/list │ │ 目录浏览 / 多选 / 下载 │
|
||
│ GET /drive/download │ │ ↓ ipc │
|
||
│ ↑ 只能访问 driveDir 内的 │ │ drive.ts (客户端) │
|
||
│ 文件, 且要带对 token │ │ listDrive / downloadDrive… │
|
||
└────────────────────────────┘ └──────────────────────────────┘
|
||
```
|
||
|
||
- **文件服务器启动即开启**: `FileServer` 本来就在应用启动时跑起来了 (端口 47901),
|
||
网盘只是给它加了 3 个 `/drive/*` 路由, 不需要额外进程。
|
||
- **共享目录**: 设置 → 网盘 → 共享目录, 默认 `~/Documents/LocalNetMsg/网盘`。
|
||
对端**只能看到这个目录里的内容**, 子目录也跳不出去。
|
||
- **访问令牌**: 每台机器一个长期 token (`userData/data/drive.token`), 随局域网发现包广播,
|
||
对端拿它调 `/drive/*`。关掉"启用网盘"开关或 token 不符都会 403。
|
||
|
||
## 2. 协议
|
||
|
||
| 接口 | 说明 |
|
||
|---|---|
|
||
| `GET /drive/meta?token=` | 取网盘根目录 (仅提示用) |
|
||
| `GET /drive/list?token=&path=` | 列目录, `path` 是相对网盘根的路径 (`''` = 根) |
|
||
| `GET /drive/download?token=&path=` | 下载文件 (流式, `Content-Disposition: attachment`) |
|
||
|
||
返回的条目:
|
||
|
||
```ts
|
||
interface DriveEntry {
|
||
name: string // 文件名
|
||
path: string // 相对网盘根的路径 (下载时用它)
|
||
size: number
|
||
mtime: number
|
||
isDir: boolean
|
||
}
|
||
```
|
||
|
||
## 3. 安全
|
||
|
||
| 风险 | 处理 |
|
||
|---|---|
|
||
| 越权读任意文件 | 路径必须落在 `driveDir` 内 (resolve 后前缀校验), `..` 一律拒绝 |
|
||
| 局域网陌生人访问 | 每次请求校验 token; 开关关掉直接 404 |
|
||
| 对方版本太老 | 老版本没有 token 字段 → 控制端显示"对方版本暂不支持网盘" |
|
||
|
||
自测覆盖: `npm run selftest -- drive` (D1–D7), 包含目录穿越和错误 token 的用例。
|
||
|
||
## 4. 用法
|
||
|
||
1. 把要共享的文件丢进网盘目录 (设置里可以改位置, 面板里有"打开文件夹")
|
||
2. 在聊天框切到 **网盘** tab → 看到对方网盘的文件列表
|
||
3. 点目录进去, 勾选文件 → **下载选中**
|
||
4. 文件落到本机接收目录 (设置 → 接收目录), 面板里能看到逐个进度
|
||
|
||
**目录也支持**:
|
||
- 点目录名可以进去, "上一级"回退, 面包屑显示当前位置
|
||
- 目录行也能打勾 → **整个目录递归下载**, 本地保持原有层级
|
||
(下载 `产品文档/` → 本机得到 `产品文档/需求说明.md`、`产品文档/原型图/xx.png`)
|
||
- 递归深度上限 12 层, 防止异常目录结构把进程拖死
|
||
|
||
对方从我的网盘下载文件时, 本机会弹一条提示, 并记进审计日志 (`drive.download`)。
|