迅雷API下载任务排查说明.md

迅雷(cnk3x/xunlei)API 下载任务排查说明(v2:问题已解决)

v2 更新(2026-08-31 04:5x,DSH 会话):"API 建任务不被 CLI 认领"问题已解决——根因是任务 body 构造错误,修正后 API 建的任务被 CLI 立即认领并完整下载(哈希与源一致)。 v1(2026-08-31 04:31):首次排查,确认 API 认证可用但建任务无效,交接给后续会话。 机器:DSH(192.168.31.76,迅雷 Web UI :2345,容器名 xunlei,cnk3x/xunlei + xunlei-pan-cli 3.21.0)


〇、v2 结论速览(本次突破)

  1. API 建任务不生效的根因 = 任务 body 字段错误:v1 用的 space:"" + params.folder + params.predict_type 是错的;正确 body 必须带 space=device_id#...、params.target=device_id#...、params.parent_folder_id=<目录ID>、total_file_count、file_id:""。
  2. 修正后实测通过:API 创建 → CLI 15~20s 内认领(PENDING→RUNNING)→ 下载引擎跑起来(11.2MB/s)→ 完成(PHASE_TYPE_COMPLETE),checked_size 314,581,680/314,581,680(100%)。
  3. 下载文件哈希与源完全一致:QQ_9.9.33_260813_x64_01.exe(314,581,680 字节)本地 sha256=b25c0d3ce9df764074a9118d0ded927e1b2d7ebf60e306112e8df18a040ec492 = GitHub 源 digest(GitHub API 返回的 asset digest)。迅雷多线程下载无损坏。
  4. 用户给的 qqdl.gtimg.cn 链接在本机无法下载(curl/python requests/迅雷下载 SDK 全部 403 Forbidden,含官网无 sign 直链、各 CDN 边缘 IP、带 UA/Referer/cookie/代理),是腾讯 CDN 拒绝本机网络,与迅雷流程无关。改用 GitHub 上完全相同的官方构建文件验证了流程。
  5. v1 的对照任务(QQ-test/QQ-test2,错误 body)仍然 PENDING 未认领,作为"错误 body 的对照证据"保留在任务列表。

一、正确创建下载任务的完整调用(v2,已实测可用)

1. 提取 pan-auth JWT(每次实时提取,约 3 天有效)

PAGE=$(curl -s "http://127.0.0.1:2345/webman/3rdparty/pan-xunlei-com/index.cgi/")
JWT=$(echo "$PAGE" | grep -oE 'function uiauth[^}]*return "[^"]+"' | grep -oE '"[^"]+"' | tr -d '"')

认证头:pan-auth: $JWT、Device-Space: ""(必须空串)、Content-Type: application/json。 (x-syno-token 只是 webman CSRF,不是 API 认证。)

2. 获取设备 ID 与下载根目录 ID

BASE="http://127.0.0.1:2345/webman/3rdparty/pan-xunlei-com/index.cgi"
# 设备 ID(runner 任务的 params.target)
curl -s "$BASE/drive/v1/tasks?type=user%23runner&device_space=" -H "pan-auth: $JWT" -H "Device-Space: "
# → tasks[0].params.target = "device_id#85292dba0b98d9d02db23e5509bc36d6"(本机)
# 下载根目录 ID(drive#folder 列表)
curl -s "$BASE/drive/v1/files?space=<urlencode(device_id)>&limit=200&parent_id=&filters=%7B%22kind%22%3A%7B%22eq%22%3A%22drive%23folder%22%7D%7D&page_token=&device_space=" \
  -H "pan-auth: $JWT" -H "Device-Space: "
# → files[0].id = "84b584c0ee8a20b73ad3a408b9f9b109"(/downloads/ 根目录)

3. (可选,UI 会先做)注册下载路径

curl -s -X POST "$BASE/device/download_path" -H "pan-auth: $JWT" -H "Device-Space: " -H "Content-Type: application/json" \
  -d '{"file_id":"84b584c0ee8a20b73ad3a408b9f9b109"}'

4. 创建任务(关键 body,与前端 addUrlTask 完全一致)

curl -s -X POST "$BASE/drive/v1/task" -H "pan-auth: $JWT" -H "Device-Space: " -H "Content-Type: application/json" -d '{
  "type": "user#download-url",
  "name": "任意任务名",
  "file_name": "QQ_9.9.33_260813_x64_01.exe",
  "file_size": "314581680",                    # 已知大小;未知填 "0" 也可以(v1 用 0 成功落库)
  "space": "device_id#85292dba0b98d9d02db23e5509bc36d6",
  "params": {
    "target": "device_id#85292dba0b98d9d02db23e5509bc36d6",
    "url": "<下载URL>",
    "total_file_count": "1",
    "parent_folder_id": "84b584c0ee8a20b73ad3a408b9f9b109",
    "mime_type": "",                            # 或 application/octet-stream
    "file_id": ""
  }
}'
# 返回 {"HttpStatus":0,"task":{...,"id":"VP0J...","phase":"PHASE_TYPE_PENDING"}}

返回后 15~20 秒内 CLI 认领:phase → PHASE_TYPE_RUNNING,params.real_path=/downloads/<任务名>,下载目录出现 .xltd 临时文件。完成后 phase → PHASE_TYPE_COMPLETE,checked_size == file_size。

5. 其他可用端点


二、v1 遗留问题根因分析(已解决,留档)

三、本次实测的两个任务(v2)

任务body结果
QQ-CLI-test(VP0JQJlN…,已删)正确 body + qqdl.gtimg.cn 链接✅ 被 CLI 认领(RUNNING),但下载源 403 → 下载引擎报 task 1001 status is Failed error
QQ-GH-test → 改名 QQ_9.9.33_260813_x64_01.exe(VP0JRxCz…)正确 body + GitHub 同文件镜像✅ 认领 → 11.2MB/s 下载 → COMPLETE,314,581,680 字节,sha256 与源一致
QQ-test / QQ-test2(v1 遗留)错误 body(space:"" + folder/predict_type)❌ 仍 PENDING,未被认领(对照证据,保留)

四、qqdl.gtimg.cn 403 排查记录(v2 修正:非全局拦截,分文件/CDN 行为)

4.1 案例 A:QQ NT 9.9.33 Windows exe(Lego Server → 403,下载失败)

链接 https://qqdl.gtimg.cn/qqfile/QQNTV2/9.9.33/release/497e2f1f/QQ_9.9.33_260813_x64_01.exe?sign=ef09ff4053edda86ecd7cb1d8726bcd1&t=1788121505:

4.2 案例 B:QQ NT 3.2.32 Linux deb(tencent-cos → 200,直接成功!)

链接 https://qqdl.gtimg.cn/qqfile/QQNTV2/9.9.33/release/3f89efc5/QQ_3.2.32_260812_amd64_01.deb?sign=5a418a6bdab5cf591cc8ba4c9ea36ff5&t=1788156000(2026-08-31 13:5x 实测):

4.3 UI 解析文件名

POST drive/v1/resource/list(body {"urls":"<链接>"})可探测链接元信息(与 UI 添加链接同款):本次返回 name: QQ_3.2.32_260812_amd64_01.deb, file_count: 1。注意落盘文件名 = 任务 name 而非 file_name,用 drive/v1/resource/list 解析出的 name 作为任务 name 即可让落盘文件名正确(本次实测任务名 QQ-deb-test 落盘为 QQ-deb-test,后手动 mv 改名)。

4.4 案例 C:QQ NT 3.2.32 Linux loongarch64 deb(tencent-cos → 200,直接成功 + 文件名直接正确)

链接 https://qqdl.gtimg.cn/qqfile/QQNTV2/9.9.33/release/3f89efc5/QQ_3.2.32_260812_loongarch64_01.deb?sign=b3ddab317c297fdd00efe781afba6faa&t=1788156389(2026-08-31 14:0x 实测):

五、运维经验(本次新踩/确认)

  1. 容器重启:CLI 云连接(watchMqtt / MySync.Reverse)会周期性掉线,掉线后 drive/v1/* 接口可能长时间无响应(本地 device/now 仍秒回)。docker restart xunlei 可恢复(约 25s 内 runner 重新 start)。重启前确认无正在下载的任务(看 xunlei-downloads/ 下有无 .xltd)。
  2. CLI 上报云端的 PATCH 有已知噪音:phase can not update from [PHASE_TYPE_RUNNING] to [PHASE_TYPE_PENDING](error_code 9, HttpStatus 400)——CLI 重启后旧任务状态同步的已知现象,不影响新任务。
  3. 下载是否开始以 .xltd 文件增长为准;任务 message="已添加" 只是已认领。
  4. 下载完成的文件名为任务 name(不是 file_name),如任务名 QQ-GH-test 落盘为 /downloads/QQ-GH-test(无扩展名),需要的话任务创建后用 mv 改名。

六、任务现状(2026-08-31 14:0x)

下载此文件