PHP中Content-Disposition文件名在Safari显示乱码问题求助
问题分析与解决办法
问题根源
你遇到的Safari中西里尔字符文件名乱码,核心原因是不同浏览器对Content-Disposition头里的文件名编码处理标准不一致:
- Chrome、Firefox等现代浏览器支持直接在
filename参数中使用UTF-8编码字符; - Safari(尤其是桌面端及旧版本移动端)不识别这种直接的UTF-8输出,会把UTF-8字节按ISO-8859-1解析,最终出现类似
ÐÐ¸Ð·Ð½ÐµÑ lite - ÐÑÐ°Ñ talk.mp3的乱码。
你的代码直接将西里尔字符文件名写入filename参数,未做标准化编码处理,这就是问题所在。
修复代码
修改Content-Disposition头的设置,采用RFC 5987标准的编码格式,同时保留兼容参数,确保所有浏览器都能正确解析:
$src_file = ROOT_PATH . '/files/uploads/' . substr( $track_file['name'], 0, 2) . '/' . $track_file['name']; if(file_exists($src_file)) { $filename = $track_file['title'] . '.mp3'; // 对文件名做URL编码,符合RFC 5987标准 $encoded_filename = rawurlencode($filename); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); // 同时提供兼容旧浏览器的filename参数,以及标准的filename*参数 header("Content-Disposition: attachment; filename=\"{$filename}\"; filename*=UTF-8''{$encoded_filename}"); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($src_file)); ob_clean(); flush(); readfile($src_file); exit; }
说明
filename*=UTF-8''{$encoded_filename}是RFC 5987定义的标准格式,明确告知浏览器文件名采用UTF-8编码,Safari能正确识别该参数;- 保留原
filename=\"{$filename}\"是为了兼容不支持RFC 5987的旧浏览器; - 使用
rawurlencode()而非urlencode(),因为前者符合RFC 3986编码规范,更适配HTTP头场景。
内容的提问来源于stack exchange,提问作者Юрий Кружевицких
相关产品推荐
相关产品推荐

