'_', '\\' => '_']); if (trim($filename) === '') { $filename = 'download'; } // Legacy filename= parameter: ASCII only. '%' is stripped because // several clients percent-decode this value (the reason Symfony // rejects it outright); '"' and '\' survive via quoted-string // escaping below. Non-ASCII transliterates where possible. $ascii = preg_replace('/[^\x20-\x7E]/', '', str_replace('%', '', Str::ascii($filename))) ?? ''; if (trim($ascii) === '') { $ascii = 'download'; } $header = $disposition.'; filename="'.addcslashes($ascii, '"\\').'"'; // Only when the ASCII form lost something: the RFC 8187 ext-value // carrying the real name, which every current browser prefers over // filename= when both are present. if ($ascii !== $filename) { $header .= "; filename*=utf-8''".rawurlencode($filename); } return $header; } }