You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者Юрий Кружевицких

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:50:31