Two parameters describe one download name
Content-Disposition carries a disposition type, normally attachment or inline, followed by parameters. The plain filename parameter is the compatibility fallback. The filename* parameter uses the extended syntax charset'language'percent-encoded-value, which is how non-ASCII characters travel safely in a header field.
- Quote the plain filename whenever it contains a space or a separator character.
- Send filename* whenever the name contains anything outside US-ASCII.
- Keep both: old clients read one, current clients read the other.
Quoting solves separators, not encoding
Wrapping a name in double quotes lets it contain spaces, commas, and semicolons without ending the parameter early. It does nothing for character encoding. Putting raw UTF-8 bytes inside the quotes produces a mangled name in some clients and a rejected header in others, because header field values are defined in terms of ASCII.
Encode the extended value over UTF-8 octets
The extended value is built by encoding the name as UTF-8 and then percent-encoding the octets that are not allowed unescaped. A common mistake is to rely on a percent-encoding helper that leaves characters such as ! ' ( ) and * untouched, since those are legal in a URI component but not in this parameter. Declare UTF-8 explicitly and leave the language field empty unless it is genuinely known.
Sanitize the name before it reaches the header
A filename that arrives from user input can contain path separators, parent-directory segments, control characters, or a newline that splits the header. Strip directory components and control characters before building the value, and decide deliberately between attachment, which prompts a download, and inline, which lets the browser render the file in place.
Which parameter a client uses
| Header sent | Current clients | Legacy clients |
|---|---|---|
| filename only, plain ASCII | Uses it | Uses it |
| filename* only | Uses it | May fall back to a name derived from the URL |
| Both parameters | Required to prefer filename* | Ignores filename* and uses the ASCII name |