IT技术博客大学习 共学习 共进步

如何在PHP下载文件名中解决乱码

PHPor 的Blog 2009-12-02 23:04:38 浏览 3,463 次

通过把Content-Type设置为application/octet-stream, 可以把动态生成的内容当作文件来下载,相信这个大家都会。 那么用Content-Disposition设置下载的文件名, 这个也有不少人知道吧。 基本上,下载程序都是这么写的:

以下是代码片段:
<?php
 $filename = "document.txt";
 header(’Content-Type: application/octet-stream’);
 header(’Content-Disposition: attachment; filename=’ . $filename);
 print "Hello!";
?>

这样用浏览器打开之后,就可以下载document.txt。

但是,如果$filename是UTF-8编码的,有些浏览器就无法正常处理了。 比如把上面那个程序稍稍改一下:

以下是代码片段:
<?php
 $filename = "中文 文件名.txt";
 header(’Content-Type: application/octet-stream’);
 header(’Content-Disposition: attachment; filename=’ . $filename);
 print "Hello!";
?>

把程序保存成UTF-8编码再访问,IE6下载的文件名就会乱码。 FF3下下载的文件名就只有“中文”两个字。Opera 9下一切正常。

输出的header实际上是这样子:

以下是引用片段:
Content-Disposition: attachment; filename=中文 文件名.txt

其实按照RFC2231的定义, 多语言编码的Content-Disposition应该这么定义:

以下是引用片段:
Content-Disposition: attachment; filename*="utf8’’%E4%B8%AD%E6%96%87%20%E6%96%87%E4%BB%B6%E5%90%8D.txt"

即:

filename后面的等号之前要加 *   
filename的值用单引号分成三段,分别是字符集(utf8)、语言(空)和urlencode过的文件名。   
最好加上双引号,否则文件名中空格后面的部分在Firefox中显示不出来   
注意urlencode的结果与php的urlencode函数结果不太相同,php的urlencode会把空格替换成+,而这里需要替换成%20

经过试验,发现几种主流浏览器的支持情况如下:

以下是代码片段:
 IE6              attachment; filename="<URL编码之后的UTF-8文件名>"          
 FF3              attachment; filename="UTF-8文件名"          
 attachment; filename*="utf8’’<URL编码之后的UTF-8文件名>"          
 O9              attachment; filename="UTF-8文件名"          
 Safari3(Win)              貌似不支持?上述方法都不行     
     
    
这样看来,程序必须得这样写才能支持所有主流浏览器:
以下是代码片段:
<?php
 $ua = $_SERVER["HTTP_USER_AGENT"];
 $filename = "中文 文件名.txt";
 $encoded_filename = urlencode($filename);
 $encoded_filename = str_replace("+", "%20", $encoded_filename);
 header(’Content-Type: application/octet-stream’);
 if (preg_match("/MSIE/", $ua)) 
 {  
  header(’Content-Disposition: attachment; 
  filename="’ . $encoded_filename . ’"’);
 } 
 else if (preg_match("/Firefox/", $ua)) 
 {
  header(’Content-Disposition: attachment; filename*="utf8\’\’’ . $filename . ’"’);
 } 
 else 
 {  
  header(’Content-Disposition: attachment; filename="’ . $filename . ’"’);
 }
 print ’ABC’;
?>           

建议继续学习

  1. php实现百度音乐采集下载 (阅读 5,403)
  2. 让PHP更快的提供文件下载 (阅读 5,322)
  3. windows下压缩包在linux解压乱码的解决办法 (阅读 5,304)
  4. Linux screen窗口中文乱码问题 (阅读 5,286)
  5. curl测试下载速度 (阅读 5,183)
  6. linux下vim的编译以及终端乱码的最终解决方案 (阅读 4,742)
  7. pptx,docx,xlsx 文件下载问题 (阅读 4,321)
  8. java中文乱码解决之道(六)—–javaWeb中的编码解码 (阅读 4,142)
  9. java中文乱码解决之道(一)—–认识字符集 (阅读 3,643)
  10. PHP截取汉字出现乱码的解决方法 (阅读 3,622)