网站提供下载服务时经常需要实现一个强制下载功能(即强制弹出下载对话框),并且文件名保持和用户之前上传时相同。 效果如下图:
Content-Disposition
使用 HTTP Header 的 Content-Disposition: attachment 可以实现下载时强制弹出下载对话框。
由于HTTP协议规定,通信内容使用US ASCII编码,就是只能使用英文字符集。若要使用其他字符集,必须根据RFC3986使用百分号将字符串编码。
Content-Disposition: attachment; filename=filename.ext
Content-Disposition: attachment; filename*=charset'lang'encoded-filename.ext
如果不进行编码会出现,用户保存文件文件名会是乱码。如下图:
不过关于Content-Disposition的RFC6266规范是2011年6月才纳入HTTP标准。 浏览器方面我测试了主流浏览器,Firefox 、 Chrome 、 Opera 、 Safari ,都支持新标准规定的 filename,不出意料,万恶的IE并不支持这个规范。不过我还是很吃惊,IE10竟然也不支持filename。
按照规范输出Content-Disposition的PHP代码如下:
if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $originfile ) . '"' );
}
else
{
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $originfile ) );
}
注意编码时使用rawurlencode
而不是urlencode
,二者的区别在于前者把空格编码为%20,而后者是+。在stackoverflow上关于这两个函数有更详细的讨论,PHP - urlencode vs rawurlencode?。
Content-Disposition: attachment; filename=filename.ext
Content-Disposition: attachment; filename*=charset'lang'encoded-filename.ext
if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $originfile ) . '"' );
}
else
{
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $originfile ) );
}
rawurlencode
而不是urlencode
,二者的区别在于前者把空格编码为%20,而后者是+。在stackoverflow上关于这两个函数有更详细的讨论,PHP - urlencode vs rawurlencode?。Content-Type
浏览器对已知类型的文件(如jpg、pdf、txt等)直接在浏览器内打开,我们通过设置http头中的 Content-Type 来改变浏览器认知的文件类型。 这里把Content-Type 设置为octet-stream,也就是二进制文件流。这样浏览器就会直接打开文件,而不是在浏览器内打开。
Content-Type: application/octet-stream
Content-Type: application/octet-stream
完整PHP代码
$filename = '中文文件名.txt';
header('Content-Type: application/octet-stream');
if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $originfile ) . '"' );
}
else
{
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $originfile ) );
}
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($filename));
常见MIME类型例表:
$filename = '中文文件名.txt';
header('Content-Type: application/octet-stream');
if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $originfile ) . '"' );
}
else
{
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $originfile ) );
}
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($filename));
序号
|
内容类型
|
文件扩展名
|
描述
|
1
|
application/msword
|
doc
|
Microsoft Word
|
2
|
application/octet-stream
|
dms lha lzh exe class
|
可执行程序
|
3
|
application/pdf
|
pdf
|
Adobe Acrobat
|
4
|
application/postscript
|
ai eps ps
|
PostScript
|
5
|
appication/powerpoint
|
ppt
|
Microsoft Powerpoint
|
6
|
appication/rtf
|
rtf
|
rtf 格式
|
7
|
appication/x-compress
|
z
|
unix 压缩文件
|
8
|
application/x-gzip
|
gz
|
gzip
|
9
|
application/x-gtar
|
gtar
|
tar 文档 (gnu 格式 )
|
10
|
application/x-shockwave-flash
|
swf
|
MacroMedia Flash
|
11
|
application/x-tar
|
tar
|
tar(4.3BSD)
|
12
|
application/zip
|
zip
|
winzip
|
13
|
audio/basic
|
au snd
|
sun/next 声音文件
|
14
|
audio/mpeg
|
mpeg mp2
|
Mpeg 声音文件
|
15
|
audio/x-aiff
|
mid midi rmf
|
Midi 格式
|
16
|
audio/x-pn-realaudio
|
ram ra
|
Real Audio 声音
|
17
|
audio/x-pn-realaudio-plugin
|
rpm
|
Real Audio 插件
|
18
|
audio/x-wav
|
wav
|
Microsoft Windows 声音
|
19
|
image/cgm
|
cgm
|
计算机图形元文件
|
20
|
image/gif
|
gif
|
COMPUSERVE GIF 图像
|
21
|
image/jpeg
|
jpeg jpg jpe
|
JPEG 图像
|
22
|
image/png
|
png
|
PNG 图像
|
23
|
text/html
|
HTML
| |
24
|
text/plain
|
TXT
| |
25
|
text/xml
|
XML
| |
26
|
text/json
|
评论
发表评论