Files

178 lines
6.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"fmt"
"io"
"strings"
)
const rootHelp = `ufile-cli — 面向自动化与 Agent 的 ufile 命令行客户端
用法:
ufile-cli [全局选项] <命令> [命令选项]
Agent 快速开始:
printf '%s\n' "$UFILE_PASSWORD" | ufile-cli -H https://ufile.example.com auth login -U agent --password-stdin
ufile-cli upload ./result.zip -R 1d -D 5
ufile-cli download Ab3dE8xP -C 123456 -O ./result.zip
命令:
auth login 登录并安全保存 30 天 Cookie 会话
auth whoami 输出当前登录用户和权限
auth logout 注销当前会话并清除本地凭据
upload 上传文件;默认自动生成 6 位取件码
download 下载文件;直接下载,不执行额外的取件校验
version 输出版本、提交和构建时间
help [命令] 显示根帮助或指定命令的详细帮助
全局选项(必须写在命令之前):
-H, --host URL ufile 服务地址;--server 是等价别名
--config PATH 配置文件路径
--timeout TIME 单次请求超时,默认 10m;0 表示不限制
--help 显示帮助
-V, --version 输出版本信息
环境变量:
UFILE_HOST 服务地址;UFILE_SERVER 是兼容别名
UFILE_SESSION 临时覆盖配置文件中的会话 Cookie
UFILE_USERNAME auth login 的默认用户名
UFILE_PASSWORD auth login 的非交互密码;优先使用密钥管理器注入
UFILE_CONFIG 默认配置文件路径
输出契约:
成功结果以单个 JSON 对象写入 stdout。
错误以单个 JSON 对象写入 stderr,并返回非零退出码。
download -O - 是唯一例外:stdout 只包含原始文件字节,不输出 JSON。
Agent 应以退出码判断成功,不要解析本地化的 message 文案。
错误 JSON:
{"error":{"code":"permission_denied","message":"没有上传权限","httpStatus":403}}
退出码:
0 成功
1 未分类错误
2 参数或用法错误
3 未登录、会话过期或认证失败
4 权限不足、缺少取件码或业务限制
5 文件不存在、已失效或取件码错误
6 服务端输入校验失败
7 网络错误或服务端内部错误
8 本地配置或文件读写错误
安全约定:
upload 默认生成取件码;只有显式传入 --no-pickup-code 才公开文件。
错误或缺失的取件码累计 5 次会使服务端删除整个文件。
download 不会预先调用校验接口,避免一次操作产生多次校验请求。
密码不能作为命令行参数传入,避免出现在进程列表和 Agent 日志中。
pickupCode 和 downloadUrl 可能包含访问凭据,不应写入公开日志。
详细帮助:
ufile-cli help auth
ufile-cli help upload
ufile-cli help download
`
const authHelp = `ufile-cli auth — 管理 Cookie 会话
用法:
ufile-cli [全局选项] auth <login|whoami|logout> [选项]
登录:
ufile-cli -H https://ufile.example.com auth login -U USER
printf '%s\n' "$UFILE_PASSWORD" | ufile-cli -H https://ufile.example.com auth login -U USER --password-stdin
login 选项:
-U, --username USER 用户名;也可使用 UFILE_USERNAME
--password-stdin 从标准输入读取一行密码,适合 Agent 和 CI
--help 显示本帮助
密码来源优先级:
1. --password-stdin
2. UFILE_PASSWORD
3. 交互式终端中的隐藏输入
说明:
会话 Cookie 有效期由服务端决定,目前为 30 天。
密码永远不会写入配置文件。
首次登录后必须改密的账号,需要先在 Web 界面完成密码修改。
`
const uploadHelp = `ufile-cli upload — 上传文件并输出分享信息
用法:
ufile-cli [全局选项] upload <文件路径> [选项]
command | ufile-cli [全局选项] upload - -N <文件名> [选项]
示例:
ufile-cli upload ./report.zip -R 1d -D 5
ufile-cli upload ./public.txt -R 1h -D 1 --no-pickup-code
ufile-cli upload ./secret.pdf -P 123456
command | ufile-cli upload - -N result.txt -R 8h
选项:
-R, --retention VALUE 保留时间:1h、8h、1d、3d、forever;默认 1d
-D, --downloads VALUE 下载次数:1-99 或 unlimited;默认 5
-P, --pickup-code CODE 使用指定的 6 位数字取件码
--no-pickup-code 明确创建无需取件码的公开分享
-N, --name NAME 从标准输入上传时必需的文件名
--content-type TYPE 覆盖根据扩展名推断的 MIME 类型
--help 显示本帮助
安全与权限:
未指定 -P 或 --no-pickup-code 时,会使用密码学安全随机数自动生成取件码。
-P 与 --no-pickup-code 不能同时使用。
普通上传单文件最大 10 MiB,且最多保留 10 个有效文件。
forever、unlimited 和超过 10 MiB 的文件需要高级上传权限。
成功 JSON 字段:
hash、name、size、expiresAt、maxDownloads、pickupCode、downloadUrl、previewUrl
示例输出:
{"hash":"Ab3dE8xP","name":"report.zip","size":1024,"expiresAt":"2026-09-21T12:00:00Z","maxDownloads":5,"pickupCode":"123456","downloadUrl":"https://ufile.example.com/uf/Ab3dE8xP?code=123456","previewUrl":"https://ufile.example.com/uf/Ab3dE8xP?code=123456&preview=true"}
`
const downloadHelp = `ufile-cli download — 下载一个公开分享文件
用法:
ufile-cli [全局选项] download <8位文件码> -O <输出路径> [选项]
示例:
ufile-cli download Ab3dE8xP -C 123456 -O ./report.zip
ufile-cli download Ab3dE8xP -O ./public.txt
ufile-cli download Ab3dE8xP -C 123456 -O - > report.zip
选项:
-C, --code CODE 6 位数字取件码
-O, --output PATH 输出路径;使用 - 将原始文件字节写入 stdout
--force 覆盖已存在的目标文件
--help 显示本帮助
重要副作用:
每次成功下载都会消耗一次访问次数;次数耗尽后服务端删除文件。
缺失或错误的取件码也会累计失败;达到 5 次时服务端删除文件。
为减少风险,本命令直接下载,不会先请求 /api/pickup 校验。
本地文件先写入同目录临时文件,成功后再重命名。
输出:
普通路径成功时,stdout 输出包含 path、name、size、contentType 的 JSON。
-O - 成功时,stdout 仅包含文件字节;错误 JSON 仍写入 stderr。
`
func printHelp(out, errOut io.Writer, topic string) int {
switch strings.TrimSpace(topic) {
case "", "root":
_, _ = io.WriteString(out, rootHelp)
case "auth", "auth login", "auth whoami", "auth logout":
_, _ = io.WriteString(out, authHelp)
case "upload":
_, _ = io.WriteString(out, uploadHelp)
case "download":
_, _ = io.WriteString(out, downloadHelp)
case "version":
fmt.Fprintln(out, "用法:ufile-cli version\n\n以 JSON 输出 version、commit 和 date。")
default:
return writeCommandError(errOut, usageError(fmt.Sprintf("未知帮助主题 %q", topic)))
}
return exitOK
}