Skip to content

fix: 下载扩展名优先采用响应文件名 - #417

Open
Isilsolme wants to merge 1 commit into
SPlayer-Dev:devfrom
Isilsolme:fix/download-extension-from-disposition
Open

Isilsolme wants to merge 1 commit into
SPlayer-Dev:devfrom
Isilsolme:fix/download-extension-from-disposition

Conversation

@Isilsolme

@Isilsolme Isilsolme commented Oct 25, 2026 •

Copy link
Copy Markdown

改动类型

  • 缺陷修复(fix)

是否包含破坏性变更

  • 否

改动说明

下载落盘时的扩展名推断里,content-disposition 只在流媒体分支被采信,其余来源完全依赖 declaredFormat:

  • 网易官方下载 / 播放接口会带 format,没问题;
  • 插件音源(resolveByPlugin)只返回 url,没有 declaredFormat,因此只能走 Content-Type → URL 后缀 → 兜底 .mp3;QQ 音乐 / 酷狗的内置分支同样只返回 { url }。

于是会出现「服务器已经写明文件名是 .flac,保存下来却是 .mp3」的情况:插件音源给出的下载地址常常是一个会 302 到 CDN 的接口地址(路径没有后缀),而 CDN 的 Content-Type 又不在 MIME_EXT 表里(例如腾讯 CDN 用 audio/x-ogg 返回 FLAC),最后一档兜底成 .mp3——文件内容是 FLAC,名字却是 MP3。

这个 PR 把「服务器返回的文件名」提升为所有下载来源的通用信号:

  • 新增 extensionFromDisposition():从 content-disposition 的 filename / filename* 里取扩展名,且只接受 KNOWN_EXTS 内的音频格式,避免把奇怪的参数当成扩展名;
  • 下载器改为 req.declaredFormat || extensionFromDisposition(...):平台声明的格式仍然最优先(网易等现有行为不变),缺声明时采信服务器文件名,最后才回退到原有的 Content-Type / URL 后缀推断;
  • 顺带把原先只写在流媒体分支里的那段正则收拢进同一个工具函数,避免两处逻辑各自漂移。

改动只作用于扩展名推断,不改变请求、落盘、写标签等流程。

关联 Issue

无(没有找到对应的 issue;如果希望我先开 issue 再关联,请告知)

测试情况

Windows 11、Node 24.15.0、pnpm 12.15.0,基于 dev 当前最新提交 006c5806:

pnpm install --frozen-lockfile    # 跳过 Electron 二进制与原生模块重编,与本次改动无关
pnpm typecheck                    # tsc node + vue-tsc web  ->  通过
pnpm lint                         # eslint                  ->  通过
pnpm test                         # 63 files / 488 tests    ->  通过
npx prettier@3 --check <改动文件>  #                          ->  通过

功能验证:

  1. 用 Node 的类型剥离直接加载改动后的 electron/main/utils/filename.ts,按下载器采用的同一表达式(declaredFormat || extensionFromDisposition(...))跑了 10 个用例,含真实抓到的响应头:
    • attachment; filename*=UTF-8''F000004b7rQP486g8d.flac + audio/x-ogg + 无后缀 URL → .flac(改动前是 .mp3)
    • filename="M800004b7rQP486g8d.mp3" + audio/mpeg → .mp3
    • 没有 content-disposition → 仍按 MIME → URL 后缀 → .mp3 依次回退,行为与改动前一致
    • 服务器文件名不是已知音频扩展名(track.weird)→ 不采信,继续回退
    • declaredFormat 存在时仍然优先(网易官方接口行为不变)
  2. 端到端:某个插件音源返回 https://<site>/plug/down.php?...,服务端响应为 content-disposition: attachment; filename*=UTF-8''F000004b7rQP486g8d.flac、content-type: audio/x-ogg、content-length: 20335993;改动后落盘文件名 .flac,首字节 fLaC,体积与 content-length 一致。

自查清单

  • 本 PR 只包含一个主要修复,没有夹带无关改动
  • 已在本地完整验证过(typecheck / lint / test 全绿,见上),AI 生成的代码同样自行测试并审阅

@Isilsolme

Copy link
Copy Markdown
Author

补充本地验证:已在 dev 最新提交上安装依赖并跑完 pnpm typecheck / pnpm lint / pnpm test,全部通过(63 个测试文件、488 个用例),具体命令见 PR 描述里的“测试情况”。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant