Skip to content

fix: decode percent-encoded file names when saving downloads - #1426

Merged
tw93 merged 1 commit into
tw93:mainfrom
NgoQuocViet2001:fix-download-filename-decoding
Oct 30, 2026
Merged

tw93 merged 1 commit into
tw93:mainfrom
NgoQuocViet2001:fix-download-filename-decoding

Conversation

@NgoQuocViet2001

Copy link
Copy Markdown
Contributor

Two kinds of download take their file name from the last URL path segment: links intercepted as downloads that have no download attribute, and the context-menu "Download image" / "Download file" items. That segment comes from the serialized pathname and was never decoded. So a link to /files/Annual Report.pdf saved as Annual%20Report.pdf, and /报告.pdf saved as %E6%8A%A5%E5%91%8A.pdf. Browsers decode this segment, so Chrome or Safari save the same link as Annual Report.pdf. On the Windows same-origin path, the encoded name also became the download attribute of the transient anchor. WebView2 then used it as is, unless the server sent a Content-Disposition name.

This change decodes the segment in getFilenameFromUrl. The old encoded name is kept in three cases: decoding fails, the result would contain a path separator or a character Windows rejects in file names, or it would contain a control/format character such as U+202E. The data: URI branch is unchanged.

  • Ran: npx vitest run tests/unit/event-link-guard.test.js, 55 passed. The new decode, download_file and native Windows tests fail on main.
  • Ran: npx vitest run, 743 passed and 3 skipped. The 2 symlink cases in local-staging.test.ts also fail on main here.
  • Checked: prettier --check on both touched files.

getFilenameFromUrl took the last segment of the serialized pathname
without decoding it, so a link to "Annual Report.pdf" or "报告.pdf" was
saved as "Annual%20Report.pdf" or "%E6%8A%A5%E5%91%8A.pdf". Decode the
segment the way browsers do, and keep the encoded form when decoding
fails or would produce a separator, a reserved or control character.
@tw93
tw93 merged commit eddc4bd into tw93:main Oct 30, 2026
9 checks passed
@tw93

tw93 commented Oct 30, 2026

Copy link
Copy Markdown
Owner

@NgoQuocViet2001 Thanks for this, the fallback for unsafe names is exactly the boundary I'd want here. Merged into main, so downloads like Annual%20Report.pdf will be saved as Annual Report.pdf from the next release.

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.

2 participants