DSH 资料站 FTP 自动上传方案
把 one 学习资料站每次更新后的 index.html 和新页面,自动上传到 FTP 网站空间的完整方案:
架构流程、涉及文件、凭据安全、配置项、实测结果与边界说明。
01需求与目标
- 核心目标:每次
index.html被更新、或新增了.html页面后,自动同步到网站空间。 - 目标站点:一个 FTP 网站空间(服务器地址保存在 dsh 凭据文件中,不对外公开)。
- 安全要求:凭据受保护——不写入脚本、不写入系统注册表、不随站点上传。
- 易用要求:日常只需双击一个入口,其余自动化完成。
02整体方案与流程
在原有"问答 → 生成网页 → 刷新入口"的基础上,追加一步自动上传:
双击入口更新入口.bat
→
重建入口页update-index.ps1
→
读取凭据~/.dsh/.credentials.yaml
→
上传所有 HTMLupload-ftp.ps1
→
网站空间ftp://<服务器>/
🔄 自动上传的触发点
上传由
update-index.ps1 在重建入口之后自动调用。因此无论手动运行脚本,还是双击
更新入口.bat,都会在刷新入口的同时完成上传。
03涉及文件
| 文件 | 作用 | 改动性质 |
|---|---|---|
| upload-ftp.ps1 | 新增:用 curl.exe 遍历 *.html 逐个 FTP 上传;从 dsh 凭据文件读账号/密码。(curl 会把中文文件名按 UTF-8 发送,避免服务器上文件名乱码) |
新增 |
| update-index.ps1 | 修改:重建入口页后自动调用 upload-ftp.ps1。 |
修改 |
| 更新入口.bat | 修改:双击入口,标题/文案更新为"更新 + 上传"。 | 修改 |
| ~/.dsh/.credentials.yaml | 修改:新增 DSH_FTP_USER / DSH_FTP_PASS 两行(dsh 凭据文件)。 |
修改 |
04凭据安全方案
凭据存放在 dsh 自带的凭据文件(~/.dsh/.credentials.yaml,与已有的
DEEPSEEK_API_KEY 同处),上传脚本运行时自动读取:
# ~/.dsh/.credentials.yaml
DEEPSEEK_API_KEY: ...
DSH_FTP_USER: 你的账号
DSH_FTP_PASS: 你的密码
🔐 为什么这样存
- 不写脚本:凭据不出现源码/脚本里。
- 不写注册表:不修改系统环境变量,不动电脑系统。
- 不随站点上传:凭据在
~/.dsh下,与站点目录隔离。 - 可兜底:环境变量
DSH_FTP_USER/DSH_FTP_PASS可用作兜底;缺失时脚本报错并提示。
05配置项
| 项 | 来源 | 默认 / 说明 |
|---|---|---|
| host | dsh 凭据文件 / 环境变量 DSH_FTP_HOST | <服务器地址·不公开> |
| port | dsh 凭据文件 / 环境变量 DSH_FTP_PORT | "21"(必须写成字符串,见下) |
| user | dsh 凭据文件 / DSH_FTP_USER | 必填 |
| pass | dsh 凭据文件 / DSH_FTP_PASS | 必填 |
| 远程目录 | 环境变量 DSH_FTP_DIR | 空 = 根目录;可填 /sub |
上传方式为覆盖式:已存在的文件也会重新上传,因此新增与修改都能同步到服务器。
06实测验证
✅ 验证结果
在无任何环境变量的情况下运行,脚本从 dsh 凭据文件读到账号/密码,
10 个 HTML 全部上传成功到
ftp://<服务器>/,包括 index.html 及各内容页。
07常见问题排查
上线初期遇到并已修复的三个问题,都藏在配置与编码细节里:
7.1 凭据值必须是字符串,且用 ASCII 引号
dsh 读取 ~/.dsh/.credentials.yaml 时要求每个值都必须是字符串
(源码 dsh-credentials-local 中 typeof value !== "string" 即抛错),空串也会报错。因此:
| 写法 | YAML 解析结果 | 结果 |
|---|---|---|
| DSH_FTP_PORT: "21" | 字符串 "21" | ✅ 正确 |
| DSH_FTP_PORT: 21 | 整数 21 | ❌ dsh 报 must be a string |
| DSH_FTP_PORT: “21” | 字符串 "“21”"(弯引号被当普通字符) | ❌ 上传脚本 URL 乱码 |
⚠️ 弯引号的坑
从文档 / 微信 / Word 复制值进 yaml 时,容易带入中文弯引号
“”。YAML 不把它当引号语法,会当作
普通字符拼进字符串——dsh 类型检查能过(因为它确实是字符串),但上传脚本的 Trim('"') 剥不掉弯引号,
端口被读成 “21”,拼出 ftp://…:“21”/,curl 报 bad/illegal format。
所以务必用 ASCII 直引号("21")或直接不带引号但与字符串要求不冲突的值。
7.2 改脚本后要保持 UTF-8 BOM
Windows PowerShell 5.1 对无 BOM 的 .ps1 按系统 ANSI(GBK)读取,中文会变乱码甚至
解析失败。脚本必须保存为带 BOM 的 UTF-8(首字节 EF BB BF)。用编辑器改动
upload-ftp.ps1 后,若它曾被去 BOM 保存,要用带 BOM 方式重新保存(可对照 update-index.ps1,
它始终带 BOM)。
7.3 排查思路
- 报
curl: (3) URL using bad/illegal format→ 八成是 host / port 被弯引号污染,先看upload-ftp.ps1打印的ftp://…地址。 - 启动 dsh 报
… must be a string→ 凭据值写成了裸数字/布尔,加 ASCII 引号。 - 脚本解析报"字符串缺少终止符 / 乱码" → BOM 丢了,用带 BOM UTF-8 重存。
08边界与注意事项
- 远程目录默认根目录:若网站在服务器上的实际路径在子目录,需设置
DSH_FTP_DIR。 - 中文文件名按 UTF-8 上传:用
curl.exe上传,文件名按 UTF-8 发送,中文文件名在服务器上不会乱码。 (FtpWebRequest会按系统 ANSI/GBK 编码文件名,导致服务器上中文文件名乱码,因此不再使用。) - 只传 HTML:.md 源文件不在上传范围(按需求)。
- 中文脚本需 UTF-8 BOM:Windows PowerShell 5.1 会按 GBK 读无 BOM 脚本导致乱码,脚本均保持带 BOM 的 UTF-8。
- 凭据改动时机:改了 dsh 凭据文件后,下次运行上传脚本即生效。
- 暂停上传:把
update-index.ps1末尾调用upload-ftp.ps1的两行注释掉即可。
09延伸方向
🚧 可选增强
若想要网页 GUI 的 FTP 配置表单(在 dsh 设置界面直接填账号/密码保存),需要开发一个 Cordis
设置分节插件并在浏览器侧渲染。工作量和风险均大于当前方案;当前"凭据在 dsh 设置文件"的方式已满足
"受保护、不改系统"的要求,可先用。