php做下载文件的实现代码及文件名中乱码解决方法


Posted in PHP onFebruary 03, 2011

最近有人问我做下载文件的方法,对于php方法如下:

<?php 
header("Content-Type: application/force-download"); 
header("Content-Disposition: attachment; filename=ins.jpg"); 
readfile("imgs/test_Zoom.jpg"); 
?>

第一行代码是强制下载;
第二行代码是给下载的内容指定一个名字;
第三行代码是把下载的内容读进文件中。
如何在PHP下载文件名中解决乱码
通过把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'; 
?>
PHP 相关文章推荐
简单的PHP缓存设计实现代码
Sep 30 PHP
php三维数组去重(示例代码)
Nov 26 PHP
php判断类是否存在函数class_exists用法分析
Nov 14 PHP
Codeigniter检测表单post数据的方法
Mar 21 PHP
php按字符无乱码截取中文的方法
Mar 27 PHP
php调用KyotoTycoon简单实例
Apr 02 PHP
php基本函数汇总
Jul 09 PHP
php实现网站顶踩功能的完整前端代码
Jul 19 PHP
PHP将URL转换成短网址的算法分享
Sep 13 PHP
PHP面向对象程序设计组合模式与装饰模式详解
Dec 02 PHP
PHP实现的redis主从数据库状态检测功能示例
Jul 20 PHP
thinkphp5.0整合phpsocketio完整攻略(绕坑)
Oct 12 PHP
PHP+SQL 注入攻击的技术实现以及预防办法
Jan 27 #PHP
php5 apache 2.2 webservice 创建与配置(java)
Jan 27 #PHP
使用XDebug调试及单元测试覆盖率分析
Jan 27 #PHP
仿AS3实现PHP 事件机制实现代码
Jan 27 #PHP
PHP 命名空间实例说明
Jan 27 #PHP
PHP中利用substr_replace将指定两位置之间的字符替换为*号
Jan 27 #PHP
PHP Session_Regenerate_ID函数双释放内存破坏漏洞
Jan 27 #PHP
You might like
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
smarty模板引擎中变量及变量修饰器用法实例
2015/01/22 PHP
PHPExcel 修改已存在Excel的方法
2018/05/03 PHP
jQuery 创建Dom元素
2010/05/07 Javascript
document.getElementById方法在Firefox与IE中的区别
2010/05/18 Javascript
ComboBox 和 DateField 在IE下消失的解决方法
2013/08/30 Javascript
深入理解JS继承和原型链的问题
2016/12/17 Javascript
bootstrap表格内容过长时用省略号表示的解决方法
2017/11/21 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
JavaScript实现简单的文本逐字打印效果示例
2018/04/12 Javascript
Angular5中提取公共组件之radio list的实例代码
2018/07/10 Javascript
JS实现获取毫秒值及转换成年月日时分秒的方法
2018/08/15 Javascript
理顺8个版本vue的区别(小结)
2018/09/17 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
2019/07/25 jQuery
jQuery设置下拉框显示与隐藏效果的方法分析
2019/09/15 jQuery
vue-router路由懒加载及实现的3种方式
2021/02/28 Vue.js
Python复制目录结构脚本代码分享
2015/03/06 Python
Python入门之modf()方法的使用
2015/05/15 Python
Python按行读取文件的简单实现方法
2016/06/22 Python
python实现发送邮件功能
2017/07/22 Python
Python实现求解括号匹配问题的方法
2018/04/17 Python
对python xlrd读取datetime类型数据的方法详解
2018/12/26 Python
python opencv图片编码为h264文件的实例
2019/12/12 Python
关于python 跨域处理方式详解
2020/03/28 Python
如何利用python正则表达式匹配版本信息
2020/12/09 Python
世界上最具创新性的增强型知名运动品牌:Proviz
2018/04/03 全球购物
大学生水文观测实习自我鉴定
2013/09/29 职场文书
门卫班长岗位职责
2013/12/15 职场文书
质量管理标语
2014/06/12 职场文书
大学生简历求职信
2014/06/24 职场文书
学习党代会心得体会
2014/09/05 职场文书
学习计划书怎么写
2014/09/15 职场文书
民政局副局长民主生活会个人整改措施
2014/10/04 职场文书
主持稿开场白
2015/06/01 职场文书
redis中lua脚本使用教程
2021/11/01 Redis
Typescript类型系统FLOW静态检查基本规范
2022/05/25 Javascript