HTTP协议header中Content-Disposition中文文件名乱码

在做文件下载时当文件名为中文时经常会出现乱码现象。 
参考文章 http://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/ 

本文就详细给出案例来解决这一乱码问题以及还一直未解决的一个疑问欢迎大家一起来探讨。 
大体的原因就是header中只支持ASCII所以我们传输的文件名必须是ASCII当文件名为中文时必须要将该中文转换成ASCII。 
转换方式有很多 
方式一将中文文件名用ISO-8859-1进行重新编码如headers.add("Content-disposition","attachment;filename="+new String("中国".getBytes("UTF-8"),"ISO-8859-1")+".txt"); 
方式二可以对中文文件名使用url编码如headers.add("Content-disposition","attachment;filename="+URLEncoder.encode("中国","UTF-8")+".txt"); 
疑问中文文件名转换成ASCII后传给浏览器浏览器遇到一堆ASCII如何能正确的还原出来我们原来的中文文件名的呢 

实验案例 
乱码现象如下 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/test/httpEntity1",method=RequestMethod.GET)

    public HttpEntity<String> testHttpEntity1() throws UnsupportedEncodingException{

        String body="abc";

        HttpHeaders headers=new HttpHeaders();

        headers.add("Content-disposition","attachment;filename=中国.txt");

        HttpEntity<String> ret=new HttpEntity<String>(body,headers);

        return ret;

    }

这里的filename直接使用中文文件然后就造成了下面的乱码现象 

 
文件名后缀也完全变了。 

原因就是header只支持ASCII所以我们要把"中国"转换成ASCII。 
解决方案一将中文文件名用ISO-8859-1进行重新编码 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/test/httpEntity",method=RequestMethod.GET)

    public HttpEntity<String> testHttpEntity() throws UnsupportedEncodingException{

        String body="abc";

        HttpHeaders headers=new HttpHeaders();

        headers.add("Content-disposition","attachment;filename="+new String("中国".getBytes("UTF-8"),"ISO-8859-1")+".txt");

        HttpEntity<String> ret=new HttpEntity<String>(body,headers);

        return ret;

    }

chrome为 
 
IE11为 

 

chrome解决了乱码现象但IE没有。但是你是否想过浏览器面对一堆Content-disposition:attachment;filename=中å½.txt它又是如何来正确显示的中文文件名"中国.txt"的呢它肯定要对中å½重新进行UTF-8编码才能正确显示出"中国"即必须进行类似如下的操作new String("中å½".getBytes("ISO-8859-1"),"UTF-8")才能正常显示出"中国.txt"。而IE11进行的类似操作为new String("中å½".getBytes("ISO-8859-1"),"GBK")。 
同样的实验只是把UTF-8改成GBK 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/test/httpEntity",method=RequestMethod.GET)

    public HttpEntity<String> testHttpEntity() throws UnsupportedEncodingException{

        String body="abc";

        HttpHeaders headers=new HttpHeaders();

        headers.add("Content-disposition","attachment;filename="+new String("中国".getBytes("GBK"),"ISO-8859-1")+".txt");

        HttpEntity<String> ret=new HttpEntity<String>(body,headers);

        return ret;

    }

chrome为 
 
IE11为 
 
IE11和chrmoe都能正确显示面对Content-disposition:attachment;filename=Öйú.txt浏览器也必须进行如下类似的操作才能正确还原出"中国"new String("Öйú".getBytes("ISO-8859-1"),"GBK")。 
这里就可以提出我们的疑问了浏览器面对中å½、Öйú都能正确还原出"中国"选择UTF-8还是GBK它到底是怎么做到的呢依据又是什么呢难道它是要计算出概率这便是我的疑问还请大家一起探讨和研究。 

接下来说说其他的解决方案 
解决方案二可以对中文文件名使用url编码 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/test/httpEntity",method=RequestMethod.GET)

    public HttpEntity<String> testHttpEntity() throws UnsupportedEncodingException{

        String body="abc";

        HttpHeaders headers=new HttpHeaders();

        headers.add("Content-disposition","attachment;filename="+URLEncoder.encode("中国","UTF-8")+".txt");

        HttpEntity<String> ret=new HttpEntity<String>(body,headers);

        return ret;

    }

chrome为 
 
IE11为 

 

也能正常显示出"中国.txt"。 
然而将该方案的UTF-8换成GBK浏览器却不支持了。 
如下 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/test/httpEntity",method=RequestMethod.GET)

    public HttpEntity<String> testHttpEntity() throws UnsupportedEncodingException{

        String body="abc";

        HttpHeaders headers=new HttpHeaders();

        headers.add("Content-disposition","attachment;filename="+URLEncoder.encode("中国","GBK")+".txt");

        HttpEntity<String> ret=new HttpEntity<String>(body,headers);

        return ret;

    }

chrome为 
 
文件名也全变了。 
IE11为 

 
这里就是说对于URL编码支持UTF-8其他的好像还不支持。 

解决方案三 
使用最新的解决方案即filename*=charset'lang'value。charset则是给浏览器指明以什么编码方式来还原中文文件名。 
如filename*=UTF-8''value其中value为原始数据的UTF-8形式的URL编码。 
如下 

?


1

2

3

4

5

6

7

8

@RequestMapping(value="/HttpEntity",method=RequestMethod.GET)         

    public HttpEntity<String> testHttpEntity() throws UnsupportedEncodingException{

        HttpHeaders headers=new HttpHeaders();//filename="+URLEncoder.encode("中国","UTF-8")+";

        String body="abc";

        headers.add("Content-Disposition","attachment;filename*=UTF-8''"+URLEncoder.encode("中国","UTF-8")+".txt");

        HttpEntity<String> ret=new HttpEntity<String>(body, headers);

        return ret;

    }

chrome为 

 
IE11为 

 
都能够正确显示。 
若使用headers.add("Content-Disposition","attachment;filename*=GBK''"+URLEncoder.encode("中国","UTF-8")+".txt"),对此chrome则是按照GBK方式来还原中文文件名的所以就会变成 

 
造成乱码。而IE11则直接是 

 

若使用headers.add("Content-disposition","attachment;filename*=GBK''"+URLEncoder.encode("中国","GBK")+".txt") 
chrome为 

 
IE11为 

 
即IE11仅支持filename*=UTF-8编码形式的。 
然后就是headers.add("Content-disposition","attachment;filename="+URLEncoder.encode("中国","UTF-8")+".txt;filename*=UTF-8''"+URLEncoder.encode("中国","UTF-8")+".txt");filename和filename*可以组合使用来解决跨浏览器的问题。 

对于上面提出的疑问还请网友们解答。

时间: 2025-01-01 07:32:19

HTTP协议header中Content-Disposition中文文件名乱码的相关文章

PHP中file_exists()判断中文文件名无效的解决方法_php技巧

本文实例讲述了PHP中file_exists()判断中文文件名无效的解决方法.分享给大家供大家参考.具体方法如下: php中判断文件是否存在我们会使用file_exists函数或is_file函数,但在使用file_exists时如果你文件名或路径是中文在uft8编码文档时是无效.本文就来解决此问题,下面我们一起来看看. 定义和用法:file_exists() 函数检查文件或目录是否存在. 如果指定的文件或目录存在则返回 true,否则返回 false. 例子1 复制代码 代码如下: <?php

lftp,gFTP和virgoFTP中文文件名乱码解决方案

今天风信网带大家来了解一下linux中FTP服务经常遇到的中文文件名乱码问题,主要针对三种常用的FTP程序来解决,分别是lftp,gFTP和virgoFTP. lftp官方:http://lftp.yar.ru/ 源码包下载地址如下: lftp-4.4.0.tar.gz (2429 kB), lftp-4.4.0.tar.bz2 (1813 kB), lftp-4.4.0.tar.xz (1395 kB) (Yaroslavl, Russia) LFTP是一款非常著名的字符界面的文件传输工具.支

通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表

 通过freemarker制作word比较简单 步骤:制作word模板.制作方式是:将模板word保存成为xml----在xml的word模板中添加相应的标记----将xml的word文件的后缀名改成ftl文件(要注意的是生成xml格式要是2003格式的xml,也就是说拿到的word模板得是2003格式的,否则用wps打开word将会出现问题)   详细步骤如下: 模板制作(将要动态显示的数据打上标记,这个标记是freemarker中的EL标记,要注意的是,要控制值为空的情况,下面${(si

php上传中文文件名乱码问题处理方案_php实例

php上传文件是最最基础的一个技术点,但是深入进去也有不少问题需要解决,这不,上传中文文件后,文件名变成了乱码. 下面是问题代码,很简单: 1.问题代码 html部分: 复制代码 代码如下:  <html>  <body>  <form action="upload_file.php" method="post"  enctype="multipart/form-data">  <label for=&q

multipart ile-MultipartFile上传文件时,中文文件名乱码怎么解决?

问题描述 MultipartFile上传文件时,中文文件名乱码怎么解决? package com.upload; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Co

linux中文文件名乱码怎么解决?

  由于安装英文版的系统不支持中文,出现中文文件名乱码. 下面操作时在centos上安装中文支持: 1)先下载并安装两个语言包: fonts-chinese-3.02-12.el5.noarch.rpm fonts-ISO8859-2-75dpi-1.0-17.1.noarch.rpm   #rpm -ivh fonts-chinese-3.02-12.el5.noarch.rpm #rpm -ivh fonts-ISO8859-2-75dpi-1.0-17.1.noarch.rpm 或者 #y

Java中HttpServletResponse响应中文出现乱码问题_java

以字符串的形式输出. 1.response.getWriter().write("您好中国hello"); 如果这样输出的话.则浏览器结果为: 2.加上代码 response.setCharacterEncoding("UTF-8"); response.getWriter().write("您好中国hello"); 则浏览器结果为: 这是因为浏览器解析问题. 加上代码: response.setHeader("Content-type

hyperlink-关于 POI 导出EXCEL 中 HyperLink 设置中文地址乱码

问题描述 关于 POI 导出EXCEL 中 HyperLink 设置中文地址乱码 请问大家一个问题,我在使用POI 3.6 的时候, 在为单元格添加HyperLink的时候,遇到添加 中文连接乱码问题,例如我的链接地址是:/file/这是PDF.PDF 在EXCEL中就会变为/file/??PDF.PDF 请问如何解决? 解决方案 http://www.iteye.com/problems/70541

Java中URL传中文时乱码的解决方法_java

前言 Java中URL传中文时乱码的问题相信不少朋友都遇到过,最近就遇到一个问题,就是在Action当中把一条中文信息绑定在URL的后面,ActionForward到别一个页面时,用reqeust.getParameter取出是出现乱码的问题. 解决办法 1.对要进行URL传递的中文字符进行编码: String message = java.net.URLEncoder.encode("中文字符","utf-8"); 2.在取URL传递中文的页面对字符进行解码: S

escape函数解决js中ajax传递中文出现乱码问题_javascript技巧

本文实例讲述了escape函数解决js中ajax传递中文出现乱码问题,分享给大家供大家参考.具体方法如下: 一.问题描述: 本来网页特效中的escape()是将中文按iso-8859-1字符集进行url编码的,那样通过 request.getparameter()是能直接获取到请求参数的,但后来的javascript将escape()换成了unicode字符集编 码,如此一来,在jsp教程和servlet中就没法直接拿到请求参数了,具体原因我也不知道. 二.解决办法: 1.首先对中文字符进行两次