http文件服务器下载接口中文,特殊字符问题

http文件服务器文件下载接口特殊字符及乱码问题

1.Content-Disposition作用

http文件的服务器下载文件的文件名判断是根据 Content-Disposition来识别。

2.Content-Disposition编解码问题:

网上搜索解决方法及RFC规范发现Content-Disposition应该采用如下格式:


Content-Disposition:attachment;
                    filename="$encoded_fname";
                    filename*=utf-8''$encoded_fname

原因:
首先,根据 RFC 2616 所定义的 HTTP 1.1 协议( RFC 2068 是最早的版本;2616替代了2068并被最广泛使用,而后又被其他 RFC 替代,后文将会提及), HTTP 消息格式其实是基于古老的 ARPA Internet Text Messages ,而 ARPA 消息只能是 ASCII 编码的( RFC 822 Section 3 )。 RFC 2616 Section 2.2 更是再一次强调, TEXT( Section 4.2:Header 中的字段值即为 TEXT )中若要使用其他字符集,必须使用 RFC 2047 的规则将字符串编码/逃逸——必须要注意的是,这个规则原本是针对 MIME (电子邮件)的扩展,格式与百分号编码有很大不同。给一个在 MIME 中的例子:

Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
在1999年 RFC 2616 推出之时, Content-Dispostion 这个 Header 尚不是正式 HTTP 协议的一部分,只不过是因为被广泛使用而从 MIME 标准中直接借用过来了而已( RFC 2616 Section 19.5.1 )。因而几乎没有浏览器去支持 Content-Disposition 的多语言编码特性这样一个“扩展特性的扩展特性”。事实上,RFC 2616 中建议的使用 RFC 2047 来进行多语言编码的特性从未被主流浏览器支持过,所以我们也不用操心上面这个 MIME 方案了……

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

IE支持在 filename 中直接使用百分号编码:filename=”$encoded_text”(并非 MIME 编码!)。本来按照 RFC 2616 ,引号内的部分如果不是 MIME 编码,则应当直接被当作内容,就算它“看起来像是百分号编码后的字符串”;可是IE却会“自动”对这样的文件名进行解码——前提是该文件名必须有一个不会被编码的(即 ASCII)后缀名!
其他一些浏览器则支持一种更为粗暴的方式:允许在 filename=”TEXT” 中直接使用 UTF-8 编码的字符串!这也是直接违反了 RFC 2616 HTTP 头必须是 ASCII 编码的规定。
这两类浏览器的行为是彼此互不兼容的。所以你可以判断 UA 然后对IE使用前一种办法,其他浏览器使用后一种,这样便可以达到一般情况下能够 just work 的效果( Discuz 就是这么做的)。不过对于 Opera 和 Safari ,这样做可能不一定有效。

时代在进步,2010年 RFC 5987 发布,正式规定了 HTTP Header 中多语言编码的处理方式采用 parameter*=charset’lang’value 的格式,其中:

charset 和 lang 不区分大小写。
lang 是用来标注字段的语言,以供读屏软件朗诵或根据语言特性进行特殊渲染,可以留空。
value 根据 RFC 3986 Section 2.1 使用百分号编码,并且规定浏览器至少应该支持 ASCII 和 UTF-8 。
当 parameter 和 parameter* 同时出现在 HTTP 头中时,浏览器应当使用后者。
其好处是保持了向前兼容性:一来 HTTP 头仍然是 ASCII-only ,二来不支持该标准的旧版浏览器会按照当年 RFC 2616 的规定,把 parameter* 整体当作一个 field name ,从而当作一个未知的字段来忽略。随后,2011年 RFC 6266 发布,正式将 Content-Disposition 纳入 HTTP 标准,并再次强调了 RFC 5987 中多语言编码的方法,还给出了一个范例用于解决向后兼容的问题:

Content-Disposition: attachment;
filename=”EURO rates”;
filename*=utf-8”%e2%82%ac%20rates
这个例子里,filename 的值是一个同义英语词组——这样符合 RFC 2616 ,普通的字段不应当被编码;至于使用 UTF-8 只是因为它是标准中强制要求必须支持的。然而,如果我们再仔细想想——目前市场上常见的旧版本浏览器多为 IE 。如此一来,我们可以适当变通一下,将 filename 字段也直接使用百分号编码后的字符串:

Content-Disposition: attachment;
filename=”%e2%82%ac%20rates.txt”;
filename*=utf-8”%e2%82%ac%20rates.txt
对于较新的 Firefox 、 Chrome 、 Opera 、 Safari 等浏览器,都支持并会使用新标准规定的 filename* ,即使它们不会自动解码 filename 也无所谓了;而对于旧版本的IE浏览器,它们无法识别 filename* ,会将其自动忽略并使用旧的 filename(唯一的小瑕疵是必须要有一个英文后缀名)。这样一来就完美解决了多浏览器的多语言兼容问题,既不需要 UA 判断,也较为符合标准。
RFC:
http://www.ietf.org/rfc/rfc1806.txt
http://www.ietf.org/rfc/rfc2616.txt

3.Java处理


 /**
     * 下载文件时的文件名编码问题
     * @param fileStream
     * @return
     */
    private void setContentDisposition(HttpServletRequest request, HttpServletResponse response, FileStream fileStream){

        try {
            String fileName = fileStream.getFileName();
            //1. 文件名为空不处理
            if (StringUtils.isNullOrEmpty(fileName)){
                return;
            };
            //2. 文件名编码过滤
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");

            //3. 设置response头
            StringBuilder sbFileName = new StringBuilder();
            sbFileName.append("attachment");
            sbFileName.append(";filename=");
            sbFileName.append(fileName);
            sbFileName.append(";filename*=utf-8''");
            sbFileName.append(fileName);
            response.setHeader("Content-Disposition",  sbFileName.toString());

        } catch (Exception e){
            LOGGER.error("", e);
        }


    }

4.抓包实例


GET /rcs/networkapi/fnfiledownload?FileTransID=4z8w3w3u-7qq5-1035-8622-b1cf1926fb1d HTTP/1.1
Host: 10.10.12.88:8003
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0
Referer: http://10.10.12.88:8003/rcs/networkapi/fileview?FileTransID=4z8w3w3u-7qq5-1035-8622-b1cf1926fb1d
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8

HTTP/1.1 200 OK
Server: grizzly/2.3.22
Accept-Charset: utf-8
Content-Disposition: attachment;filename=%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%2B%201111%26%3B%24%28%27%28%26%28.txt;filename*=utf-8''%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%2B%201111%26%3B%24%28%27%28%26%28.txt
Content-Type: application/octet-stream;name= ,  + 1111&;$('(&(.txt
Date: Thu, 24 Aug 2017 06:36:13 GMT
Content-Length: 12

111123456789

参考:
http://www.cnblogs.com/hihtml5/p/7220188.html?utm_source=itdadao&utm_medium=referral

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帝国下载系统是一款代码完全开源、专为网站资料下载与在线影视网站提供的解决方案。功能强大,简单易用,全静态页面,完善的会员下载收费方案,全面满足免费与收费下载或影视网站需求。 帝国下载系统 2.5 升级功能列表: 1、对系统进行全面的优化、调整,包括数据库与程序代码,代码基本重写。使系统运行效率更高更稳定。 2、新增下载字母导航,可以按头字母对下载内容进行检索。 3、新增专题功能,可以对下载进行自定义分类。 4、后台分类导航加载改进,页面加载速度更快,管理效率更高。 5、后台新增管理所有下载功能,更方便管理所有下载。 6、后台管理下载支持按“置顶”、“推荐”、“审核”及多种排序方式显示。管理下载更方便。 7、下载发布界面改进,更人性化,并且增加分类时可以选择“软件表单”或者“电影表单”模式。 8、下载与在线地址支持上传文件并自动填写文件扩展名及大小;支持直接上传与选择附件目录文件两种方式。 9、支持内容页文件名自定义。 10、新增下载地址前缀功能,同时支持"HEADER"、"META"、"READ"三种下载方式。 11、管理下载新增生成单下载及批量刷新选中下载功能。更方便生成指定的内容页。 12、管理下载新增生成“首页”、“父分类页”、“当前分类页”快捷功能,增加下载后只需点击提交即可发布到前台。 13、后台可设置是否开启后台登陆验证码。 14、后台可设置增加信息后直接生成分类页及专题页。更方便。 15、新增可设置是否检查软件名重复。 16、可设置默认录入下载地址数及在线地址数。 17、后台直接设置是否开启直接下载功能。(先前版本是修改配置文件) 18、可设置整站文件扩展名。 19、列表页存放目录、内容页存放目录自定义。并将目录转移到根目录,优化SEO。 20、每组生成列表数、内容页数、自定义页面数、批量替换下载数量设置。可以依服务器配置设置。 21、支持设置生成时间间隔。解决部分空间的资源限制问题。 22、后台界面改进,使用更加方便。 23、新增后台地图导航,可以更快捷的进入相应的管理操作。 24、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 25、安全性方面更强: (1)、管理员密码采用双重md5模式,防止密码泄漏被暴力破解; (2)、登录新增认证码功能,要同时满足密码跟认证码同时正确才能登录,此功能可防止非法用户知道密码也无法登录; (3)、COOKIE认证码验证,为身份认证再加一把锁。 (4)、COOKIE前缀自定义。 26、管理员登录次数、登陆IP及最后登陆时间记录。 27、增加用户设置管理分类支持选择父分类,选择父分类会应用于子分类权限。 28、新增前台购买充值类型管理:可设置充值有效期及点数。会员购买更点数、有效期非常方便,全自动充值。 29、新增在线支付功能: (1)、支付记录管理,方便与支付接口商记录对账。 (2)、网银支付接口配置。 30、参数设置可设置前台投稿开关。 31、前后台上传文件扩展名与文件大小设置。 32、前台投稿发布软件支持直接输入地址及上传附件两种方式。 33、后台可设置是否开启评论、评论验证码、评论字数限制以衣评论屏蔽字符设置。 34、生成广告JS文件前缀设置。防止浏览器屏蔽ad文件。 35、后台备份系统升级至帝国备份王2008最新版。备份效率更高更稳定。 36、新增总的分类导航变量及间隔符设置,原来版本是手动在模板修改。 37、新增“您的位置”间隔符设置。 38、数据更新中心改进,生成内容更完备。 39、新增管理所有评论功能、并支持按软件ID、评论内容、评论IP搜索。方便管理评论。 40、分类新增分类别名、分类缩略图、分类关键字、分类简介等属性。 41、分类列表生成增加显示最大数据设置。在大数据量情况下使用。 42、分类可设置开启投稿、投稿会员组及投稿获得点数。 43、管理分类新增终极分类与非终极分类转换功能。 44、管理软件类型改进,支持不同类型设置不同的模板及设置显示最大数。 45、电影模块改进,支持视频播放器管理,可任意增加/管理播放器。视频播放器可任意扩展。播放器默认新增Mediaplay、Realplayer、FLASH与FLV 46、新增强大的批量地址替换功能,支持按分类及附件SQL条件替换下载权限、点数、下载前缀、下载地址及下载名称替换。 47、管理附件新增数据式管理与目录式管理两种方式。 48、新增自定义列表功能。可以调用各种特殊条件的列表。 49、新增自定义页面。可以后台增加单页网页。 会员功能改进: 50、可设置会员是否需要审核 51、设置注册默认会员组及赠送点数。 52、注册用户名与密码字数限制设置 53、注册用户名保留字设置
1、平台无关性是指程序编写一次,在不同的操作系统和硬件平台上都可以运行。Java语言实现平台无关性的原理是通过将Java源代码编译成字节码(bytecode),然后在不同的平台上运行Java虚拟机(JVM)来解释执行字节码,从而实现跨平台运行。 2、自动类型转换的前提是目标类型能够容纳源类型,即目标类型的取值范围大于等于源类型。转换时的优先级顺序是:byte、short、char -> int -> long -> float -> double。 3、成员变量是定义在类中的变量,它们的作用域是整个类;局部变量是定义在方法或语句块中的变量,它们的作用域只是在定义的方法或语句块中。成员变量在对象创建时会被初始化,而局部变量需要手动初始化才能使用。 4、在Java中,对象的相等是指两个对象的内容相同,而指向它们的引用相等是指两个引用指向同一个对象。可以使用equals()方法判断对象的相等,使用==判断引用的相等。 5、接口是一种特殊的抽象类,它只包含抽象方法和常量,没有实例变量和构造方法。接口与抽象类的区别在于,接口中的方法都是抽象方法,而抽象类中可以包含非抽象方法;类可以实现多个接口,但只能继承一个抽象类。 6、流是Java中用于处理输入输出的一种机制。Java语言中分为字节流和字符流两种类型。字节流以字节为单位进行读写操作,适合处理二进制文件和网络传输;字符流以字符为单位进行读写操作,适合处理文本文件和网络传输。字节流类和字符流类的区别在于它们的处理单位不同。 7、Java实现多线程有两种途径:继承Thread类和实现Runnable接口。区别在于,继承Thread类需要直接重写run()方法,而实现Runnable接口需要实现run()方法,并且可以避免单继承的限制。 8、Java应用程序是指独立的、可执行的程序,可以直接在操作系统上运行;Java小程序是指在Web浏览器中运行的程序,需要通过Java虚拟机(JVM)解释执行。 9、基本类型变量存储的是变量的值,而引用类型变量存储的是对象的地址。例如,int是基本类型变量,而String是引用类型变量。 10、JDK是Java Development Kit的缩写,是Java开发工具包的意思。JRE是Java Runtime Environment的缩写,是Java运行时环境的意思。JDK包含JRE和开发工具,JRE只包含Java虚拟机(JVM)和运行时库。 11、方法的重载是指在同一个类中定义多个同名但参数列表不同的方法;方法的覆盖是指子类重写父类的方法。区别在于,方法的重载是一个编译期概念,方法的覆盖是一个运行期概念。 12、接口是一种特殊的抽象类,它只包含抽象方法和常量,没有实例变量和构造方法。定义接口可以实现代码复用和多态性。 13、InputStream和OutputStream是字节流类,用于处理二进制文件和网络传输;Reader和Writer是字符流类,用于处理文本文件和网络传输。 14、Java程序的运行机制是先将Java源代码编译成字节码,然后在Java虚拟机(JVM)上解释执行字节码。 15、构造方法是一种特殊的方法,用于创建对象时初始化对象的属性。Java中构造方法需要满足以下条件:方法名与类名相同,没有返回类型,可以有参数。 16、方法的覆盖是指子类重写父类的方法,方法名、参数列表和返回类型必须相同;方法的重载是指在同一个类中定义多个同名但参数列表不同的方法。区别在于,方法的重载是一个编译期概念,方法的覆盖是一个运行期概念。 17、自动装箱是指将基本类型转换为对应的包装类对象,自动拆箱是指将包装类对象转换为对应的基本类型。例如,int可以自动装箱成Integer,Integer可以自动拆箱成int。 18、集合是Java中用于存储和操作数据的一种容器。常用的集合类和接口有ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。 19、流是Java中用于处理输入输出的一种机制。Java语言中分为字节流和字符流两种类型。字节流以字节为单位进行读写操作,适合处理二进制文件和网络传输;字符流以字符为单位进行读写操作,适合处理文本文件和网络传输。字节流类和字符流类的区别在于它们的处理单位不同。 20、JDBC中Driver、Connection、Statement和ResultSet分别用于连接数据库、获取数据库连接、执行SQL语句和处理查询结果。Driver是数据库驱动程序,Connection表示一个数据库连接,Statement表示一个SQL语句,ResultSet表示查询结果集。 21、使用Java程序实现流式Socket通信需要使用Socket和ServerSocket两个类。Socket类表示客户端套接字,ServerSocket类表示服务器套接字。在服务器端,先使用ServerSocket类创建一个服务器套接字,然后等待客户端连接;在客户端,使用Socket类创建一个客户端套接字,然后连接到服务器端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值