`

Unicode网页中上传下载文件时发生文件名乱码的问题

 
阅读更多
最近有一个需要支持unicode的项目在上传和下载文件时遇到文件名乱码问题. 项目背景, 这个项目关键之处在于需要支持unicode以及支持Micorosoft Internet Explorer和Netscape Navigator两种浏览器. 为了解决这个问题, 我使用以下环境进行了尝试.

J2SE : 1.5.0_04
Tomcat : 5.5.17
Microsoft Internet Explorer 6.0 with SP2
Netscape Navigator 7.1
Firefox 1.5
以及Struts 1.1 (这个基本上对此次测试不是非常重要)

上传文件

对于unicode的页面进行上传文件的时候, 我使用一个text box和一个file upload box来进行比较. 页面如下.

utf-8 upload page

 通过此页面进行文件上传后, IE, NC以及FF所传输的数据均相同. 如下

Content-Type: multipart/form-data; boundary=---------------------------282302224217945
Content-Length: 27980

-----------------------------282302224217945
Content-Disposition: form-data; name="theText"

C:\縺ゅ≠縺ゅ≠.xls
-----------------------------282302224217945
Content-Disposition: form-data; name="theFile"; filename="縺ゅ≠縺ゅ≠.xls"
Content-Type: application/vnd.ms-excel

可以看出, 对text box和file upload box中的文件名所有浏览器均采取了相同的编码. 经证实, 是上传页面的编码方式——所有浏览器均对unicode数据(utf-8)采取了本地的编码方式(这里是ms932).

在服务器端对上传的数据进行解码.

解码的方式有很多, 这里我使用最普遍以及正规的request.setCharacterEncoding的方法. 发现form表单中的text box可以被正常解码, 但是file upload box中的文件名无法通过这种方式解码. 所以只能使用手工解码.

String fixedFileName = new String(fileName.getBytes("SJIS"), "UTF-8");

其中SJIS是客户端系统的编码, UTF-8是客户端页面的编码.

上传文件测试中, 所有浏览器表现一致, 需要注意的是文件名和表单数据的不同处理方式.

下载文件

使用一个unicode的JSP页面, 在页面上有一个固定的超链接, 传递给服务器一个文件名. 服务器依照这个文件名把服务器端的文件传递给客户端.

下载页面

<%@ page language="java" contentType="text/html; charset=utf-8"%>

<meta http-equiv="content-type" content="text/html; charset=utf-8">

<href="download.do?name=ああああ.xls">ダウンロード</a>

对于这样一个页面, 当点击超链接后, 各浏览器处理方式不同

IE会把超链接依照页面当前编码方式编码(这里是utf-8)后, 发送给服务器端

GET /nsupload/download.do?name=縺ゅ≠縺ゅ≠.xls HTTP/1.1

NC和FF会把超链接依照页面编码方式编码(这里是utf-8)后, 再通过url encoding后, 发送给服务器端

GET /nsupload/download.do?name=%E3%81%82%E3%81%82%E3%81%82%E3%81%82.xls HTTP/1.1

(经证实, E38182是「あ」的unicode代码)

在服务器收到提交的数据后, 需要对其进行解码. 需要注意的是这种方式下使用request.setCharacterEncoding无效. 所以必须手工解码.

name = new String(name.getBytes("ISO-8859-1"), "UTF-8");

其中ISO-8859-1是Tomcat服务器的特性, Tomcat会把所有的数据先转换为ISO-8859-1的形式. UTF-8是实际的编码方式.

在得到文件名后, 就可以正确地读取文件, 然后把文件传递给客户端了. 其中, 文件名是保存在Http报头(header)的Content-Disposition中.

response.setHeader("Content-Disposition""inline; filename=" + _filename);
//或者
response.setHeader("Content-Disposition""attachment; filename=" + _filename);

经实验证明, 使用inline或者attachment对文件名的编码方式没有影响.

另外一个需要设置的是Content-Type.

response.setContentType("application/vnd.ms-excel");
//或者
response.setContentType("application/vnd.ms-excel; charset=UTF-8");
//或者
response.setContentType("application/x-download; name=" + _filename);

经试验证明, 使用application/*的任何形式都对文件名的编码方式没有影响.
第二点, 经试验证明, 这里的charset设置会被三种浏览器忽略, 所以设置与否影响文件名的编码方式.
第三点, 经试验证明, 这里的name设置对文件名没有任何影响.

可能还有一个属性需要注意, 就是Content-Language. 经试验证明, Content-Language有无, 或者为何值, 对文件名没有任何影响.

那么对于non-ascii的文件名如何操作才可以保证客户端可以得到正确的显示呢?

经过调查, 有三种方法(在网上搜索后认为可能这篇文章是对于这个问题探讨最深入的文章)

第一, 使用URLEncoding方法. 即对文件名进行URLEncoding.

name = URLEncoder.encode(name, "UTF-8");


这种方式适用于IE, 但是不适用于NC和FF. 在这种方式下, 网络上传输的是url encoding后的ascii编码.

Content-Disposition: inline; filename=%E3%81%82%E3%81%82%E3%81%82%E3%81%82.xls

NC和FF不能对这样的文件名进行有效的解码.

NC download

FF download

第二, 使用字符串字符集强行转换为本地字符集方法, 这样做的原理是JVM底层全部为unicode. 所以一旦一个字符串表示了正确的字符集而被存储后, 这个字符串会被转换为任意字符集.

原理二是, IE和FF对非url encoding的non-ascii文件名采用客户端系统本地的编码方式进行转换.

name = new String(name.getBytes("Shift_JIS"), "ISO-8859-1");

需要注意的是, 这里的name原本是utf-8的.

在网络上传输的为

Content-Disposition: inline; filename=ああああ.xls


经过试验, IE和FF支持这种方式, NC不支持. 表现为NC无法解析文件名.

第三种, 使用Base64编码文件名. 原理是这种做法符合RFC2047的定义.

name = javax.mail.internet.MimeUtility.encodeText(name, "UTF-8""B");

使用到了JavaMail中的Base64编码的类MimeUtility.

在网络上传输的为经过Base64编码的ascii字符.

Content-Disposition: inline; filename==?UTF-8?B?44GC44GC44GC44GCLnhscw==?=

只有FF支持这种方式, IE表现为无法解析文件名, NC表现为忽略Base64编码.

NC base64 download

IE Base64 download

以上三种方法是目前来讲, 使浏览器可以正确下载non-ascii文件名的方法. 其中IE支持两种(url encoding和force transform), FF支持两种(force transform和base64 encoding), NC一种都不支持.

关于这次调查的结果, 对于NC多说两句, 我以为这个结果是由于NC 7.1和Tomcat 5.5不兼容造成的. Tomcat 5.5要求必须把所有报头先转变为ISO-8859-1的格式, 而NC 7.1却无法直接对ISO-8859-1进行正确的解析或者说是解析功能比较弱. 如果有时间, 我会继续验证非unicode的情况以及NC 8的情况.


---2006年9月14日21:00 补充---

在NC 8.1上进行了测试, 测试结果是NC 8.1支持方法三, 即base64 encoding.

nc81-base64-down.jpg
分享到:
评论

相关推荐

    解决python3中解压zip文件是文件名乱码的问题

    在zip标准中,对文件名的 encoding 用的不是 unicode,而可能是各种软件根据系统的默认字符集来采用(此为猜测),因此zipfile中根据文件 flag 检测的时候,只支持 cp437 和 utf-8。 具体就是查找 zipfile.py 源代码...

    中文内码转换巨匠 v3.21

    一款深受用户欢迎的中文内码转换软件。它基于GBK码与BIG5码进行中文简繁文档与BIG5繁体文档双向转换,为中文简繁交流架起桥梁。崭新接口的v3.0版新增内码和字符的双向转换功能,可显示任何字符的...转换网页文件时,能

    完美解决Python2操作中文名文件乱码的问题

    Python2默认是不支持中文的,一般我们在程序的开头加上#-*-coding:utf-8-*-来解决这个问题,但是在我用open()方法打开文件时,中文名字却显示成了乱码。 我先给大家说说Python中的编码问题,Python中的字符串的大概...

    VbsUnpacker - EXE还原成原始VBS - VBS转EXE脚本提取工具(2.4.5)

    Vbs Unpacker 2.4.5 - by Icy_Ybk (-- 软件介绍 --) Vbs Unpacker 是 Vbs2Exe 的克星,能够将 VBS 文件从 Vbs2Exe 打包好的 EXE 中...解决了旧版本部分输出文件产生的乱码问题(Unicode) 非重复,而是出新版了。

    java反编译工具 jad

    对于很多人说jad反编译后中文显示乱码,其实显示的是unicode字符;jad命令中有可以让中文正常显示的 -8 - 将Unicode字符转换为ANSI字符串,如果输出字符串是中文的话一定要加上这个参数才能正确显示。 最常用的反...

    txtFormat去广告绿色最新版

    2 单击列表中的一个文件名来打开此文件 3 批处理就是一次性依次处理整个目录中的所有文件。 对于格式整理而言,通常情况下, 你只需使用“格式整理”就够了。建议多进行一次“格式整理”处理。这样可以把广告清除得...

    MP3 信息修改工具 Mp3tag 3.06 中文多语免费版.zip

    所谓ID3-Tag 信息,就是在MP3文件中加入曲名,演唱者,专辑,年月,流派,注释等信息,便于您收集歌曲。其实winamp中带有编辑器,只是把它做的方便一点。 Mp3tag 中文版可以以文件名批量添加媒体元信息,根据媒体元...

    手机 pdf 阅读器

    阅读到尾部弹出“上一个/下一个”窗口中的文件名过长不刷新的问题 偏好切换时亮度混乱的问题 在NOKIA上,当系统路径设置为根目录是无法启动的BUG E398上可以开关键盘灯 UIQ系统在退出时可以保持亮度 索爱上按“返回...

    TrueCrypt的国内延伸版本CnCrypt V1.11(单一文件绿色版)

    BUG修改项目为UNICODE,避免部分路径出现乱码的问题 BUG修改对Win8.1,Win10版本获取错误的问题 BUG当前存在模态窗口时,禁用托盘菜单项,避免重叠模态窗口 BUG修改程序启动时驱动器列表变灰的BUG BUG修改添加收藏夹...

    gbsetup.exe

    在处理DBF文件时,进程中不仅能重置中文数据库,还能自动更正中文字段名,告知出错文件名。 本工具简洁直观,功能强悍。只需菜单点选文件类型,设置文件位置,一键转换,即可实现批量文件极速转码。它支持VFP6,...

    网站开发防止中文乱码需要了解的codepage的重要性小结

    文件夹名,文件名等都是unicode的,任何语言系统下都能正常显示。 二、输入法:微软拼音输出的是Unicode的,智能ABC输出是简体中文的(所以智能ABC在非简体中文系统根本不能用,只能打英文)。 三、网页的textarea...

    textpro 6.5及使用教程

    发现不同字符时,程序在下方状态栏提示不相同的字符及其位置,当前激活的文件中,光标自动移到不相同的字符处,以便直接编辑,另一个未激活文件窗口的显示位置自动随之移动。 比较时自动忽略回车和半角空格,还有...

    Jar电子书制作工具

    1.自动识别GBK、UTF_8和Unicode各种txt文件; 2.支持目录、单个文件、多文件拖入以及直接添加内容的方式; 3.自动对大尺寸内容进行拆分,拆分的内容大小为150K,拆分不会产生乱码; 4.支持目前市面绝大多数手机;...

    txt 转换成jar 工具

    2 单击列表中的一个文件名来打开此文件 3 批处理就是一次性依次处理整个目录中的所有文件。 对于格式整理而言,通常情况下, 你只需使用"格式整理"就够了。 建议多进行一次“格式整理”处理。这样可以把广告清除得...

    官方最新发布的Textpro6.5及其教程

    发现不同字符时,程序在下方状态栏提示不相同的字符及其位置,当前激活的文件中,光标自动移到不相同的字符处,以便直接编辑,另一个未激活文件窗口的显示位置自动随之移动。 比较时自动忽略回车和半角空格,还有...

    zarchiver解压器下载 安卓版

    《ZArchiver解压工具》是一款系统安全类软件 强大的压缩/解压工具,能够解压的文件类型非常广泛。 使用ZArchiver你可以: -创建格式为:7z (7zip),zip,bzip...-支持unicode格式文件名(UTF-8); -完美支持中文不乱码。

    ZArchiver Donate 0.8.4.apk

    ZArchiver是一款强大的压缩和解压缩软件,支持rar,zip,7z等等,不像androidzip一样解压7z错误,还支持带密码的rar压缩文件,支持中文文件名,(这是安卓上唯一...&gt; 支持unicode格式文件名(UTF-8); &gt;完美支持中文不乱码

    经典的java反编译工具 jad

    很多人困扰,反编译之后中文显示乱码问题,其实显示的不是乱码,是unicode字符。 -8 - 将Unicode字符转换为ANSI字符串,如果输出字符串是中文的话一定要加上这个参数才能正确显示。 最常用的反编译指令如下所示: ...

    功能超强的网络流媒体地址嗅探工具__酷抓coojah_6.8.193.0614终结版

    *修正刀锋下载同时下载多个RTMP文件时文件不能播放的问题 ----------------------------------------------------------- CooJah 6.1.1.3 Build091021 Blader 4.1.1.0 Build091021 +Support RTMP authorization ...

    ZArchiver解压缩工具 0.8.0

    软件名称:ZArchiver解压缩工具 APK名称:ru.zdevs.zarchiver.pro 最新版本:0.8.0 支持ROM:4.0及更高版本 ... 支持unicode格式文件名(UTF-8); & amp; amp; amp; amp; amp; amp; gt;完美支持中文不乱码

Global site tag (gtag.js) - Google Analytics