fix: Decode percent-encoded filenames from URLs (#12906)

getFileNameFromUrl returned the raw URL path segment, so attachments
created from a URL were stored with encoded names (e.g. "My%20File.pdf").
Decode the filename, falling back to the raw value on malformed encoding.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Moor
2026-07-06 22:57:50 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent d3c085462d
commit 236eabdcc8
2 changed files with 26 additions and 1 deletions
+18
View File
@@ -82,4 +82,22 @@ describe("getFileNameFromUrl", () => {
).toBe("file.txt");
expect(getFileNameFromUrl("https://example.com/")).toBe("");
});
it("decodes percent-encoded filenames", () => {
expect(getFileNameFromUrl("https://example.com/My%20Report.pdf")).toBe(
"My Report.pdf"
);
expect(getFileNameFromUrl("https://example.com/caf%C3%A9%20menu.png")).toBe(
"café menu.png"
);
expect(
getFileNameFromUrl("https://example.com/report%20final.pdf?v=2#top")
).toBe("report final.pdf");
});
it("falls back to the raw filename on malformed encoding", () => {
expect(getFileNameFromUrl("https://example.com/bad%name.txt")).toBe(
"bad%name.txt"
);
});
});
+8 -1
View File
@@ -157,7 +157,14 @@ export function getFileNameFromUrl(url: string) {
const urlObj = new URL(url);
const pathname = urlObj.pathname;
const filename = pathname.substring(pathname.lastIndexOf("/") + 1);
return filename;
try {
// Decode percent-encoding so the name is human readable (e.g. "My%20File.pdf" → "My File.pdf").
return decodeURIComponent(filename);
} catch (_err) {
// Malformed percent-encoding, fall back to the raw filename.
return filename;
}
} catch (_err) {
return null;
}