FileGator v7.16.8 API 使用详解

FileGator v7.16.8 HTTP JSON API 详解:会话+CSRF 双认证约定、21 条路由端点总览、认证/文件/上传下载/打包批量下载/用户管理五域逐条实测调用与回显,含 v7.16.8 返回值缺陷与排障实录。

FileGatorFileGator文件分享2026/10/30

FileGator v7.16.8 API 使用详解

目标:讲清 FileGator v7.16.8 的 HTTP JSON API——会话与 CSRF 双认证约定、全部 21 条路由端点总览、核心域(认证/文件/上传下载/打包/用户管理)的逐条实测调用与回显,以及踩坑清单。全部请求与回显均在 2026-10-30 于官方镜像部署栈上实测照抄;API 无独立 Key 体系,调用方式与前端页面完全同构。

一、环境信息

  • 实测对象:FileGator v7.16.8(官方镜像 filegator/filegator:v7.16.8,API 版本经 GET /?r=/getconfig 返回 app_version: 7.16.8 确认)
  • 实测入口:http://127.0.0.1:8149(部署见 《FileGator v7.16.8 Docker Compose 部署指南》)
  • 测试账号:admin / q1w2e3r4(改密后的管理员)、dev1 / q1w2e3r4(实测创建的 user 角色账号)
  • 路由表版本:官方仓库 backend/Controllers/routes.php(2026-10-30 实查,21 条路由)
  • 工具:curl(session cookie + CSRF 头双携带)

二、前置条件

  1. FileGator 栈已按部署指南拉起,且 admin 已改密(q1w2e3r4)。
  2. API 无 OpenAPI 文档、无独立 API Key——认证体系就是浏览器页面用的 PHP 会话,脚本化调用模拟浏览器即可。
  3. 需理解两个前置机制(本文实测结论):
    • 路由形态:所有端点走查询参数 ?r=/端点(配置 query_param 默认 'r')。直接访问 /login 等路径返回 Apache 404(官方镜像无 URL 重写规则,实测确认)。
    • CSRF 防护:GET/HEAD/OPTIONS 请求的响应头下发 X-CSRF-Token;所有 POST 请求必须回带同名请求头,否则返回 HTTP 200 + 空响应体(应用日志记 Csrf token not valid)。

三、认证与调用约定

3.1 双件套获取流程

每次脚本会话的标准开场(三步):

# 1) 匿名 GET:建立会话(cookie)+ 拿 CSRF token(响应头)
TOKEN=$(curl -s -i -c cookies.txt "http://127.0.0.1:8149/?r=/getuser" | grep -i 'x-csrf-token' | tr -d '\r' | awk '{print $2}')
echo "$TOKEN"

实测回显(token 形态为三段点分串):

2002eab0f4686bd477034893e1cf4.PDvbVu-2KR3H3KRzN8Szyc1S5ySToSdLYp2DF1oBF68.X2nvNK7ScGq1sO4gUYXem4YLgmjrmBE-OtjoIwVkdPlwWqpv1vdhcpftww
# 2) 登录(带 cookie + token)
curl -s -b cookies.txt -c cookies.txt -X POST "http://127.0.0.1:8149/?r=/login" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"username":"admin","password":"q1w2e3r4"}'

实测回显:

{"data":{"role":"admin","permissions":["read","write","upload","download","batchdownload","zip","chmod"],"homedir":"\/","username":"admin","name":"Admin"}}
# 3) 登录后必须重新 GET 一次拿新 token(登录会迁移会话 ID,旧 token 失效——实测踩坑)
TOKEN=$(curl -s -i -b cookies.txt -c cookies.txt "http://127.0.0.1:8149/?r=/getuser" | grep -i 'x-csrf-token' | tr -d '\r' | awk '{print $2}')

3.2 响应约定

  • 成功:{"data": <结果>}(列表/对象/字符串按端点不同)。
  • 业务失败:{"data":"Failed"} / {"data":"Login failed, please try again"} 等(注意 v7.16.8 部分端点 Failed 但操作实际成功,见第七章)。
  • 参数校验失败:HTTP 422 + {"<字段>":"This field is required"} 形态。
  • 认证过期:重定向回 /(HTML)或返回 guest 角色对象。
  • 全部业务端点要求 JSON 请求体(Content-Type: application/json);上传端点例外用 multipart。

四、端点总览(21 条路由全集)

按官方路由表(routes.php 2026-10-30 实查)整理,permissions 列为通过该端点所需的权限位:

方法端点(?r= 后)作用允许角色需要权限
GET/前端页面guest/user/admin-
POST/login登录guest-
POST/logout登出三角色-
GET/getuser当前用户信息三角色-
POST/changepassword改自己密码user/admin-
GET/getconfig前端配置三角色-
POST/changedir切换当前目录(会话态)三角色read
POST/getdir列目录三角色read
POST/copyitems复制三角色read+write
POST/moveitems移动三角色read+write
POST/renameitem重命名三角色read+write
POST/zipitems打包 zip三角色read+write+zip
POST/unzipitem解压三角色read+write+zip
POST/chmoditems改权限位三角色read+write+chmod
POST/deleteitems删除三角色read+write
POST/createnew新建文件/目录三角色read+write
GET/upload分块预检(chunkCheck)三角色upload
POST/upload分块上传三角色upload
GET/download单文件下载三角色download
POST/GET/batchdownload批量打包下载三角色read+download+batchdownload
GET/listusers用户列表仅 admin-
POST/storeuser建用户仅 admin-
POST/updateuser/{username}改用户仅 admin-
POST/deleteuser/{username}删用户仅 admin-
POST/savecontent保存文件内容三角色read+write

说明:表内「三角色」含 guest——guest 是否真能操作取决于其 permissions(默认 guest permissions 为空,实测不可读写)。

五、核心域逐条实测

5.1 认证域

登出(POST /logout):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/logout" -H "X-CSRF-Token: $TOKEN"

实测回显 {"data":"Logged out"};随后 getuser 返回 guest。

改密(POST /changepassword,oldpassword+newpassword 必填):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/changepassword" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"oldpassword":"admin123","newpassword":"q1w2e3r4"}'

实测回显:{"data":{"role":"admin","permissions":[...7 项...],"homedir":"\/","username":"admin","name":"Admin"}},同时 private/users.json 的 bcrypt hash 更新(实测 $2y$10$Nu35... → $2y$10$CLGlz4...)。

登录失败与锁定:错误密码返回 {"data":"Login failed, please try again"};默认连续 5 次失败锁定该 IP 15 秒(配置 lockout_attempts/lockout_timeout,可收紧)。

5.2 文件域

列目录(POST /getdir):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/getdir" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" -d '{"directory":"/"}'

实测回显:

{"data":{"location":"\/","files":[{"type":"dir","path":"\/docs","name":"docs","size":0,"time":1793341916,"permissions":755},{"type":"file","path":"\/hello.md","name":"hello.md","size":66,"time":1793341898,"permissions":644}]}}

新建(POST /createnew,type 取 file/dir):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/createnew" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"type":"dir","name":"docs","directory":"/"}'

实测:dir 返回 {"data":"Done"};file 类型返回 {"data":"Failed"} 但文件实际已创建(v7.16.8 已知缺陷,见第七章)。

写文件内容(POST /savecontent,自动创建目标文件):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/savecontent" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"directory":"/","name":"hello.md","content":"# FileGator 实测文件\n这是 B2 部署验证写入的内容。\n"}'

实测回显 {"data":"Done"}。

重命名 / 删除(renameitem 用 from/to;deleteitems 的 items 同样要对象数组):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/renameitem" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"from":"/empty.txt","to":"/empty-renamed.txt"}'
# {"data":"Done"}

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/deleteitems" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"items":[{"type":"file","path":"/empty-renamed.txt"}]}'
# {"data":"Done"}

5.3 上传下载域

上传(POST /upload,multipart,resumable.js 协议参数必带):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/upload" \
  -H "X-CSRF-Token: $TOKEN" \
  -F 'file=@upload-test.txt' \
  -F 'resumableFilename=upload-test.txt' \
  -F 'resumableRelativePath=/' \
  -F 'resumableChunkNumber=1' \
  -F 'resumableTotalChunks=1' \
  -F 'resumableTotalSize=52' \
  -F 'resumableIdentifier=uploadtesttxt52jpeg'

实测回显 {"data":"Stored"}。分块大于 1 时按 resumableChunkNumber 逐块 POST,最后一块由服务端合并落盘;漏带 resumable* 参数返回 {"data":"Error storing file"}(实测)。GET /upload 为分块预检(chunkCheck),返回已收块信息。

下载(GET /download,path 为 base64 编码的文件绝对路径):

B64=$(printf '/upload-test.txt' | base64 -w0)
curl -s -b cookies.txt -o dl-out.txt -w "HTTP:%{http_code} bytes:%{size_download} type:%{content_type}\n" \
  "http://127.0.0.1:8149/?r=/download&path=$B64"

实测回显:

HTTP:200 bytes:66 type:text/plain;charset=UTF-8

路径未 base64 编码(误用 ?file=)返回 302 重定向回首页(实测)。

5.4 打包与批量下载域

打包(POST /zipitems,items 为对象数组):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/zipitems" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"items":[{"type":"file","path":"/hello.md"},{"type":"file","path":"/upload-test.txt"}],"destination":"/","name":"archive.zip"}'

实测返回 {"data":"Failed"} 但 repository/archive.zip(351 字节,PK 文件头合法)实际已生成——以 getdir 复核为准。

批量下载(POST 建 archive → GET 取件,这是 FileGator 的「分享」形态:打包件与会话绑定,仅创建者可下载,源码 rememberBatchArchive 逻辑):

# POST:拿 uniqid
curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/batchdownload" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"items":[{"type":"file","path":"/hello.md"},{"type":"file","path":"/upload-test.txt"}]}'
# {"data":{"uniqid":"8ec8dc043ce18598179884728d72fa942237dfcdefdfa72918bbe5ce68d6d7be"}}

# GET:拉取 zip
curl -s -b cookies.txt -o batch-out.zip -w "HTTP:%{http_code} bytes:%{size_download}\n" \
  "http://127.0.0.1:8149/?r=/batchdownload&uniqid=8ec8dc043ce18598179884728d72fa942237dfcdefdfa72918bbe5ce68d6d7be"
# HTTP:200 bytes:351

解压(POST /unzipitem):{"item":"/archive.zip","destination":"/docs"} → 实测返回 {"data":"Failed"} 但两个文件已实际解压到 /docs(同款缺陷)。

5.5 用户管理域(仅 admin)

建用户(POST /storeuser):

curl -s -b cookies.txt -X POST "http://127.0.0.1:8149/?r=/storeuser" \
  -H 'Content-Type: application/json' -H "X-CSRF-Token: $TOKEN" \
  -d '{"username":"dev1","name":"Dev One","role":"user","homedir":"/docs","permissions":["read","write","upload","download"],"password":"q1w2e3r4"}'

实测回显:

{"data":{"role":"user","permissions":["read","write","upload","download"],"homedir":"\/docs","username":"dev1","name":"Dev One"}}

用户列表(GET /listusers)返回全部用户对象(含 homedir/permissions,不含明文密码);改用户(POST /updateuser/{username})与删用户(POST /deleteuser/{username})同构。实测 dev1(user 角色)访问 listusers 无权限(角色门槛生效);dev1 登录后 getdir 只见 homedir /docs 内文件(目录隔离生效)。

六、限流与其他约定

  • 登录限流:按 IP 计失败次数,默认 5 次失败锁 15 秒(lockout_attempts/lockout_timeout 可在 configuration.php 调整);自动化脚本应处理 Login failed 后的退避。
  • 无全局请求限流:路由表与源码未见令牌桶等限流层,批量脚本自控节奏。
  • 上传体积链:前端 upload_max_size(默认 100MB)→ 分块大小(默认 1MB)→ PHP 运行时限制,调参联动见 《FileGator v7.16.8 配置参数详解》 第五章。
  • 会话有效期:PHP 默认会话生命周期,脚本长跑任务建议定期重登或处理 302/guest 响应后自动重连。

七、排障实录(实测沉淀)

  1. POST 全部返回 HTTP 200 + 空响应体 CSRF token 缺失/过期。判定方法:查 private/logs/app.log 是否出现 Csrf token not valid(实测记录)。修复:重新 GET 取响应头 X-CSRF-Token 并回带;登录后必须重取(会话迁移使旧 token 失效,实测踩坑两次)。
  2. /login、/getconfig 直接访问 404 官方镜像无 URL 重写,必须用 /?r=/端点 形态(实测 404 vs 200 对照)。
  3. createnew(file)/zipitems/unzipitem 返回 Failed 但操作成功 v7.16.8 源码缺陷:控制器对无返回值的适配器方法取反判断(Filesystem::createFile 与 ZipArchiver::storeArchive 均无 return 语句,源码实查)。脚本化处理:忽略该返回值,用 getdir/宿主目录复核实际结果。
  4. items 传字符串数组报 PHP Warning/Fatal zipitems/batchdownload/deleteitems 的 items 必须是 [{"type":"file","path":"..."}] 对象数组;传 ["/hello.md"] 触发 Attempt to read property "type" on string(实测日志),zipitems 场景还会连锁 Fatal。
  5. 上传 Error storing file 缺 resumable* 参数组(前端协议必带),按 5.3 参数清单补全。
  6. 下载 302 回首页 path 参数未做 base64 编码,或文件路径在当前账号 homedir 之外(权限边界,实测行为一致)。

八、参考链接