转:正确处理浏览器在下载文件时HTTP头的编码问题(Content-Disposition)

中文文件名下载乱码根因与Content-Disposition正确解法 在Web开发中,文件下载功能看似简单,却常因HTTP响应头中的Content-Disposition处理不当而出现中文文件名乱码、下划线或缺失等问题。HTTP协议头字段受限于早期ASCII字符集设计,无法直接承载非ASCII字符,导致不同浏览器出现差异化的解析行为。为解决此问题,RFC 2231/5987提出了基于URL编码的filename*参数,通过百分号编码将中文文件名安全传递,并兼顾老浏览器的回退兼容。这一技术方案广泛应用于Python、Java、Node.js、Golang等主流后端语言,是前后端 阅读详情

原文地址:http://www.iefans.net/xiazai-wenjian-http-bianma-content-disposition


最近在做项目时遇到了一个 case :需要实现一个强制在浏览器中的下载功能(即强制让浏览器弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。

前一个需求很容易实现:使用 HTTP Header 的 Content-Disposition: attachment 即可,还可以配合 Content-Type: application/octet-stream 来确保万无一失。而后一个需求就比较蛋疼了,牵扯到 Header 的编码问题(文件名是作为 filename 参数放在 Content-Disposition 里面的)。众所周知, HTTP Header 中的 Content-Type 可以指定内容的编码,可 Header 本身的编码又该如何制定?甚至, Header 究竟是否允许非 ASCII 编码呢?

如果放任编码问题不管,那么恭喜你,你一定会遇到在某个系统及浏览器下下载文件时文件名乱码的情况。如果你尝试搜索解决,那么再一次恭喜你,你会找到一堆自相矛盾的解决方案(我可以负责任地告诉你,其中的99%都是不符合标准的 trick 罢了)。让我们来看看到底应该如何优雅完美地解决这个问题吧!<>

为了探索这个问题,我走了不少弯路。从自己尝试,到 Google 、百度(分别尝试过中英文搜索),再到阅读 Discuz 等经典项目的源码,众说纷纭、莫衷一是。最后我才想到回归 RFC ,从标准文档中找办法,果然有所收获。由于探究过程实在太曲折,我就先把标准做法写下来。

应该这样设置 Content-Disposition :

Content-Disposition: attachment;

filename="$encoded_fname";

filename*=utf-8''$encoded_fname

其中,$encoded_fname指的是将 UTF-8 编码的原始文件名按照 RFC 3986 进行百分号 urlencode 后得到的( PHP 中使用 rawurlencode() 函数)。这几行也可以合并为一行,推荐使用一个空格隔开。

另外,为了兼容 IE6 ,请保证原始文件名必须包含英文扩展名!

好了,接下来我们来看看为什么要这么做以及为什么能这么做。

首先,根据 HTTP 1.1 协议规范( RFC 2616 Section 4 ), HTTP 消息格式其实是基于古老的 ARPA INTERNET TEXT MESSAGES ( RFC 822 Section 3 ),根据其规定,消息只能是 ASCII 编码的。 RFC 2616 Section 2.2 又一次强调, TEXT 中若要使用其他字符集,必须使用 RFC 2047 的规则将字符串编码为 ASCII 码(事实上这个规则原本是针对 MIME 的扩展,使用的是 base64 编码,格式与百分号编码有很大不同)。总而言之,按照标准, HTTP Header 中的文本数据必须是 ASCII 编码的。

filename="TEXT"

;这是 RFC 2616 标准,TEXT必须是 ASCII 字符且被认为就是“原文”

filename*=charset'lang'encoded-text

;这是按照 RFC 2047 扩展后的,注意格式上的细微区别,采用 base64 编码(编码结果也是 ASCII 字符)

然而,事实上在1999年 HTTP 1.1 标准推出之时, Content-Dispostion 这个 Header 尚不是正式标准的一部分,只不过是因为被广泛使用而从 MIME 标准中直接借用过来了而已( RFC 2616 Section 19.5.1)。因而几乎没有浏览器去支持 Content-Disposition 的多语言编码特性这样一个“扩展特性的扩展特性”(事实上, HTTP 1.1 草案中建议的使用 RFC 2047 来进行多语言编码的特性从未被主流浏览器支持过)。

可是这个问题却的确是现实需要的,所以浏览器就各自想出了一些办法:

  • IE支持两种格式的混合版:filename="encoded_text" (这里采用的是百分号编码)。本来按照 RFC 2616 ,引号内的部分应当直接被当作内容,就算它“看起来像是编码后的字符串”;可是IE却会“自动”对这样的文件名进行解码——前提是该文件名必须有一个不会被编码的后缀名(即正常的英文字母后缀名)!

  • 其他一些浏览器则支持一种更为粗暴的方式——允许在 filename="TEXT" 中直接使用 UTF-8 编码的字符串!

这两类浏览器的行为是彼此互不兼容的。所以你可以判断 UA 然后对IE使用前一种办法,其他浏览器使用后一种,这样便可以达到一般情况下能够 just work 的效果( Discuz 就是这么做的)。不过对于 Opera 和 Safari ,这样做可能不一定有效。

时代在进步,2010年 RFC 5987 发布,正式规定了 HTTP Header 中多语言编码的处理方式,应当采用类似 MIME 扩展的 parameter*=charset'lang'value 的格式,但是其中 value 应根据 RFC 3986 Section 2.1 使用百分号进行编码,并且规定浏览器至少应该支持 ASCII 和 UTF-8 。随后,2011年 RFC 6266 发布,正式将 Content-Disposition 纳入 HTTP 标准,并再次强调了 RFC 5987 中多语言编码的方法,还给出了一个范例用于解决向后兼容的问题——就是我在一开始给出的例子:

Content-Disposition: attachment;

filename="encoded_text";

filename*=utf-8''encoded_text

在这个例子中,对于较新的 Firefox 、 Chrome 、 Opera 、 Safari 等浏览器,都支持新标准规定的 filename* ,并且会优先使用,所以尽管 filename=”encoded_text” 不被它们支持,仍然不会有问题;至于使用 UTF-8 只是因为它是标准中强制要求必须支持的。而对于旧版本的IE浏览器,它们无法识别后面的 filename* ,会自动忽略并使用旧的 filename 。这样一来就完美解决了多浏览器的多语言兼容问题,既不需要 UA 判断,也符合标准。

P.S. 为什么 PHP 要使用 rawurlencode() 函数呢?因为这才是真正符合 RFC 3986 的“百分号URL编码”,只是由于历史原因,之前先有了一个 urlencode() 函数用于实现 HTTP POST 中的类似的编码规则,故而只好用这么一个奇怪的名字。两者的区别在于前者会把空格编码为%20,而后者则会编码为+号。如果使用后者,那么IE6在下载带有空格的文件名时空格会变为加号。一般情况下,你是不会用到 urlencode() 这个函数的( Discuz 某些版本中错误地使用它来进行文件名编码,从而导致空格变加号的BUG)。

via:Robot Shell




【记一次采坑】content-disposition里设置附件文件名称无效 开发一个文件下载功能,想要通过HTTP的response header中的 content-disposition: attachment;filename=template.xls 设置下载文件的名称。结果下载文件的名称死活不是template.xls,而是url中最后一个路径名称(例如url为http://localhost:9018/knowledge_template,则下载的文件始终为... 阅读详情

相关推荐

Content-Disposition使用方法和注意事项

最近不少Web技术圈内的朋友在讨论协议方面的事情,有的说web开发者应该熟悉web相关的协议,有的则说不用很了解。个人认为这要分层次来看待这个问 题,对于一个新手或者刚入门的web开发人员而言,研究协议方面的东西可能会使得web开发失去趣味性、抹煞学习积极性,这类人应该更多的了解基本的 Web技术使用。而对于在该行业工作多年的老鸟来说,协议相关的内容、标准相关内容应该尽量多些的了解,因为只有这样才能使得经手的web系统更加优秀 (安全、漂亮、快速、兼容性好、体验好……)。 本文我们来说一下MIME 协议的一个扩展Content-disposition。 我们在开发web系统时有时会有以下需求

HTTP Response Header 的 Content-Disposition

因为听到有同事讨论JSP输出Excel文件的,就是在页面上有一个【导出】按钮,能够将查询结果导出到Excel文件让用户下载。有人说要用POI在后台生成临时的Excel文件,然后通过读取FileStream写入到OutputStream来解决。其实这个功能不需要这么重型的武器的,虽然很多人讨厌MS,但是不得不承认MS绝对不是乱盖的,IE和Office产品的几近完美的结合就是一个列子。页面里面的Tab

WHATIFSO 4216

Qt图形视图框架实战:QGraphicsScene、QGraphicsView与QGraphicsItem的深度应用

本文深入解析Qt图形视图框架的核心组件QGraphicsScene、QGraphicsView与QGraphicsItem的实战应用。通过“舞台、镜头与演员”的比喻,清晰阐述了三者的协作关系,并详细介绍了场景管理、多视图同步、交互增强、自定义图形项绘制与性能优化等高级技巧,帮助开发者高效构建复杂的交互式图形界面。

weixin_29251337的博客 263

正确处理浏览器在下载文件时HTTP头的编码问题(Content-Disposition)

最近在做项目时遇到了一个 case :需要实现一个强制在浏览器中的下载功能(即强制让浏览器弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。前一个需求很容易实现:使用 HTTP Header 的 Content-Disposition: attachment 即可,还可以配合 Content-Type: application/octet-stream 来确保

damoluomu的专栏 1261

HDLbits找茬实战:5个Verilog仿真Bug修复案例,新手避坑指南

本文通过HDLbits平台上的5个典型Verilog仿真Bug案例,详细解析了多路选择器位宽不匹配、模块实例化端口映射错误等常见问题,提供实用的修复方案和调试技巧,帮助Verilog新手快速掌握代码验证与仿真技能,避免常见陷阱。

weixin_42653691的博客 162

GSview5.0安装步骤及问题

GSview5.0安装步骤及问题安装步骤遇到的问题 尝试过很多对图片去白边的方法,感觉最好用最有效的还是用GSview比较好操作。本文针对gsview安装及安装过程中踩过的坑记录下来。 安装步骤 在官网下载gsv50w64.exe(或32位的),直接双击安装即可。 安装Ghostscript;注意:GSview5.0不支持最新版的Ghostscript9.54,这里用到是9.27的版本可以在Github中找到,下载gs927w64.exe,一定要安装在GSview的安装目录Ghostgum下 Gho

LilianLYN的博客 1万+

http协议之response响应详解

1,http响应 HTTP/1.1 200 OK             --响应行 Server: Apache-Coyote/1.1    --多个响应头 Content-Length: 51 Date: Sun, 28 Dec 2014 01:51:16 GMT                                 --一个空行 this is first servle

guyan1111的博客 1万+

深入解析FOC电流环PI参数整定:从理论到实践

本文深入解析了FOC(磁场定向控制)中电流环PI参数整定的核心原理与实践方法。文章从永磁同步电机模型出发,详细阐述了基于带宽与零极点对消的工程法及考虑逆变器延迟的二阶系统整定法两种经典策略,并提供了从理论计算到安全上电调试的完整步骤与常见问题解决方案,帮助工程师精准调校电机控制性能。

weixin_29164497的博客 451

【转】正确处理浏览器在下载文件时HTTP头的编码问题(Content-Disposition)

最近在做项目时遇到了一个 case :需要实现一个强制在浏览器中的下载功能(即强制让浏览器弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。 前一个需求很容易实现:使用 HTTP Header 的 Content-Disposition: attachment 即可,还可以配合 Content-Type: application/octet-stream 来...

weixin_33875839的博客 181

【操作系统】 Operation System 第二章:操作系统基础操作

2.1 操作系统的启动 (1)CPU, I/O, 内存通过总线连接。 (2)DISK:存放OS; BIOS:基本I/O处理系统( basic I/O system); Bootloader: 加载OS到内存中。 (3)当电脑通电时,段寄存器CS和指令寄存器IP能够确定一个内存地址,例如CS:IP = 0xf000:fff0. (4)POST(加电自检),寻找显卡和执行BIOS。(显示器,键盘…是否...

iwanderu的博客 1万+

智能小车避障功能的实现(cpp,ubuntu)

智能小车避障功能的实现(cpp,ubuntu)

weixin_62135607的博客 4376

(转)正确处理浏览器在下载文件时HTTP头的编码问题(Content-Disposition)

原文链接:http://www.iefans.net/xiazai-wenjian-http-bianma-content-disposition/ 最近在做项目时遇到了一个 case :需要实现一个强制在浏览器中的下载功能(即强制让浏览器弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。 前一个需求很容易实现:使用 HTTP Header 的 Conte...

cy4ttty的专栏 578

计算机组成原理(第三版)唐朔飞-第十章控制单元的设计-课后习题

计算机组成原理(第三版)唐朔飞-第十章控制单元的设计-课后习题

weixin_45735391的博客 3万+

[转] 正确处理浏览器在下载文件时HTTP头的编码问题(Content-Disposition)

最近在做项目时遇到了一个 case :需要实现一个强制在浏览器中的下载功能(即强制让浏览器弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。 前一个需求很容易实现:使用 HTTP Header 的 Content-Disposition: attachment 即可,还可以配合 Content-Type: application/octet-stre...

jzhx38745383的博客 394

SPICE仿真软件:HSPICE_(22).HSPICE仿真案例分析

通过上述案例分析,我们可以看到HSPICE仿真软件在不同电路类型和仿真场景中的应用。无论是简单的直流分析、交流分析还是复杂的暂态分析,HSPICE都能提供详细的仿真结果,帮助我们更好地理解和优化电路设计。希望这些案例能够为读者提供实用的参考和指导,进一步提升使用HSPICE进行电路仿真的能力。输入文件的编写:确保输入文件格式正确,使用注释来解释每一部分的内容。分析类型的选择:根据电路的特点选择合适的分析类型,如.DC.AC和.TRAN。输出结果的设置:使用.print命令来指定需要输出的节点电压和支路电流。

kkchenjj的博客 1309

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

正确处理下载文件时HTTP头的编码问题(Content-Disposition

最近在做项目时遇到了一个 case :需要实现一个强制下载功能(即强制弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。前一个需求很容易实现:使用 HTTP Header 的 Content-Disposition: attachment 即可,还可以配合 Content-Type: application/octet-stream来确保万无一失。而后一个需...

liutong123987的专栏 1680

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

正确处理下载文件时HTTP头的编码问题(Content-Disposition)

最近在做项目时遇到了一个 case :需要实现一个强制下载功能(即强制弹出下载对话框),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。 前一个需求很容易实现:使用 HTTPHeader的Content-Disposition: attachment即可,还可以配合Content-Type: application/octet-stream来确保万无一失。而后一个需求就比较蛋疼了,牵扯到 Header 的编码问题(文件名是作为 filename 参数放在 Content-...

努力改变人生 4194

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

探究 Content-Disposition:解决下载中文文件名乱码

直接在Content-Disposition中设置中文会导致乱码。通过Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters 中的规定设置了正确的的编码方式,从而实现正确显示中文。

liuyaqi1993的博客 2万+

兼容性处理下载文件时HTTP头的编码问题(Content-Disposition)

正确处理下载文件时HTTP头的编码问题(Content-Disposition) 最近在做项目时遇到了一个 case :需要实现一个强制下载功能(即强制弹出下载对话框,阻止浏览器尝试解析显示某些文件格式),并且文件名必须保持和用户之前上传时相同(可能包含非 ASCII 字符)。 前一个需求很容易实现:使用 HTTP Header 的Content-Disposition: attachment即可,还可以配合Content-Type: application/octet-stream来确保万无一...

細水、長流√的专栏 1162

http header中的Content-disposition

Access-Control-Expose-Headers 响应首部 Access-Control-Expose-Headers 列出了哪些首部可以作为响应的一部分暴露给外部。 默认情况下,只有六种 simple response headers (简单响应首部)可以暴露给外部: Cache-Control Content-Language Content-Type Expires Last-M...

刹那的博客 1万+

Content-Disposition 文件上传、下载 中文乱码 HTTP头 解决办法

1、文件上传 通过表单上传文件时,如果文件名存在中文则会发生乱码。 &lt;form name="myform" action="/fileManager/uploadFile" method="post" enctype="multipart/form-data" accept-charset="utf-8" &gt; &lt;input type="text&qu

VicterTian的博客 6212

IE浏览器下载中文名文件乱码,Header中Content-Disposition出现中文字导致的乱码问题

问题出现: 在项目中需要对上传到服务端的中文名文件进行下载,出现了下载文件名乱码的问题,而且这个问题只出现在IE浏览器上,如何解决这个问题,和大家分享解决方法,探讨其中的缘由。 参考文章:https://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/#comments 问题截图: 解决思路: ...

define_LIN的博客 5536
上一篇: 转:系统吞吐量(TPS)、用户并发量、性能测试概念和公式
下一篇: 转:一篇看懂数据库连接池概念、原理、运行机制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值