# T-WIN-014 发布交付:必须上传完整包 - **状态**: done - **依赖**: T-WIN-011 - **文档**: v1.6 §5.7 ## 问题 `v0.1.0` 发布到 Gitea 的 Release 资产是 ``` opendance-windows-v0.1.0.zip.part0 opendance-windows-v0.1.0.zip.part1 opendance-windows-v0.1.0.zip.part2 REASSEMBLE.txt SHA256SUMS.txt ``` 用户下载到的是**三个碎片**,必须先按 `REASSEMBLE.txt` 拼接再解压 —— 这就是"分卷有问题"。 ## 根因(实测) | 上传体积 | 结果 | |--|--| | 14 MB | 通过(HTTP 201) | | 30.5 MB | **失败 HTTP 413**(IIS「请求实体过大」页面) | | 40 MB | **失败 HTTP 413** | → 当前上限是 **IIS 默认的 `maxAllowedContentLength = 30,000,000` 字节(≈28.6 MiB)**。 整包约 38 MB(`exe` ≈104 MB 未压缩、`pck` ≈107 KB),当时被拆成每卷 13 MiB 才传上去。 ## 方案(采用 A:提高上限) - **A. 提高上限**(推荐,配置一次永久解决):IIS `maxAllowedContentLength = 268435456`(256 MB), ARR `maxRequestBytes` 同步放宽,Gitea `app.ini` `[attachment] MAX_SIZE ≥ 256 MB`, 前置 nginx(若有)`client_max_body_size 256m;`。做法见 `opendance-web/deploy/proxy/README.md`。 - B. 控制包体 ≤ 28 MB 与 C. 改分发方式(Git LFS / 走 Web 服务端 `/static`)作为备选保留。 ## 本次改动 `build/package-release.sh` 重写,落实文档 §5.7 的四条硬性要求: 1. **单个完整包**:产物只有 `opendance-windows-vX.Y.Z.zip` + `SHA256SUMS`; 脚本开头 `rm -f "$NAME.zip".part*` 清理历史分卷, 并且**超限时直接报警而绝不回退分卷**。 2. **`SHA256SUMS` 用裸文件名**,用户下载到同一目录后 `sha256sum -c SHA256SUMS` 直接可用。 3. **体积与完整性自检**: - 源产物:`exe` 校验 PE 头 `MZ`、`pck` 校验魔数 `GDPC`; - 解压后:必须同时存在 `OpenDance.exe` + `OpenDance.pck`(同目录)、 `README.txt`、`THIRD_PARTY.md`、`contracts/`,并再次校验 `MZ` / `GDPC`; - `exe` 与 `pck` 主文件名必须一致(否则 Godot 找不到资源); - 上传前打印包体大小与 IIS 上限的对比结论。 4. **记录实测上限**:脚本内置 `UPLOAD_LIMIT_BYTES=30000000` 并在发布说明中写明, 避免下次再踩。 ## 验收(文档 §5.7) | 验收项 | 结果 | |--|--| | Release 资产只有一个 `opendance-windows-vX.Y.Z.zip` + `SHA256SUMS` | ✅ 见 `dist-release/` | | 下载后可直接解压运行(`OpenDance.exe` + `.pck` 同目录),无需拼接 | ✅ 脚本解压自检覆盖 | | `sha256sum -c SHA256SUMS` 通过 | ✅ 脚本打包后立即在同一目录自校验 | ## 实测记录与一次误判更正(v0.2.0 发布时) **真实且仍然存在的限制:IIS 的 `maxAllowedContentLength`(默认 30,000,000 字节 ≈ 28.6 MiB)** | 上传体积 | 结果 | |--|--| | 927 KB / 14 MB / 16,372,427 B | 通过(HTTP 201) | | 30.5 MB | **HTTP 413**(IIS「请求实体过大」页面) | | **38,245,602 B(本整包)** | **HTTP 413** | | 40 MB | **HTTP 413** | → 这就是 Windows 整包(约 37 MB)无法上传的**唯一真实原因**;放开办法见 `opendance-web/deploy/proxy/README.md` 9.2(IIS `requestLimits` + `uploadReadAheadSize`、 ARR `maxRequestBytes`、Gitea `app.ini` 的 `[attachment] MAX_SIZE`、前置 nginx)。 **【更正】排查中曾把 500 误判为"Gitea 宿主机磁盘写满"** —— 那个结论是错的,原因是 **上传写法错误**:Gitea 的 Release 附件接口 multipart 字段名是 **`attachment`**, 用 `file=` 会得到 `HTTP 500 {"message":"","url":"…/api/swagger"}`(**空消息**, 极易误判为服务器故障)。实测对照(同一 1 KB 文件、同一 Release): | 写法 | 结果 | |--|--| | `-F "attachment=@probe.bin"` | **201** | | `--data-binary @probe.bin`(`Content-Type: application/octet-stream`,URL 带 `?name=`) | **201** | | `-F "file=@probe.bin"` | **500**(空消息) | **正确的上传写法**(本仓库发布时照抄): ```bash # 整包(multipart,字段名 attachment) curl -f -X POST -H "Authorization: token " \ -F "attachment=@opendance-windows-vX.Y.Z.zip" \ "https://gitea.kasugano.cn/api/v1/repos/zijunchiang/opendance-windows/releases//assets?name=opendance-windows-vX.Y.Z.zip" # SHA256SUMS(裸 body + ?name=) curl -f -X POST -H "Authorization: token " \ -H "Content-Type: application/octet-stream" --data-binary @SHA256SUMS \ "https://gitea.kasugano.cn/api/v1/repos/zijunchiang/opendance-windows/releases//assets?name=SHA256SUMS" ``` ## 上传前检查清单 ``` 1) bash build/export-windows.sh release # 生成 exe + pck 2) bash build/package-release.sh 0.2.0 # 单包 + SHA256SUMS + 自检 3) 看输出的「包体 / 上限」对比: - 低于 30,000,000 字节 -> 直接上传; - 超过 -> 先请运维放宽 IIS/ARR/Gitea 上限,不要拆卷。 4) Gitea Release 只上传 opendance-windows-vX.Y.Z.zip 与 SHA256SUMS 两个资产。 ```