Files
zpan/shared/content-disposition.ts
T
saltbo fa136a5112 fix(upload): make Content-Disposition Latin-1 safe for non-ASCII filenames
Uploading a file with a non-ASCII name (Chinese, emoji, …) failed with
"Failed to execute 'setRequestHeader' on 'XMLHttpRequest': String contains
non ISO-8859-1 code point." The presigned PUT's signed Content-Disposition put
the raw filename in the plain `filename="..."` parameter, which the browser
then rejects when setting it as an XHR request header.

Add a shared attachmentContentDisposition() helper that keeps `filename=`
ASCII-only and carries the real name in `filename*=UTF-8''`, and route all
three construction sites through it so the signed and client-returned values
stay identical (the value is part of the SigV4 signature).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 18:01:13 -04:00

13 lines
751 B
TypeScript

// Builds an RFC 6266 `Content-Disposition` for forced downloads.
//
// The plain `filename=` parameter must be ASCII-only: it is signed into the S3
// presigned PUT and then set as an XHR request header by the browser, and
// `XMLHttpRequest.setRequestHeader` rejects any value containing a code point
// above U+00FF ("String contains non ISO-8859-1 code point"). Non-ASCII names
// (Chinese, emoji, …) are carried losslessly by the percent-encoded
// `filename*=UTF-8''` form, which every modern browser prefers.
export function attachmentContentDisposition(name: string): string {
const asciiFallback = name.replace(/[^\x20-\x7e]|["\\]/g, '_')
return `attachment; filename="${asciiFallback}"; filename*=UTF-8''${encodeURIComponent(name)}`
}