Java Web 项目解决IE、火狐、google中文乱码的问题

最近做了一个文件上传下载的功能,但是在下载的时候,出现了一点问题,文件名包含中文的时候,IE、google浏览器文件名称没有乱码,但是火狐浏览器文件名乱码,从网上找了很久都没有解决,记录一下自己解决此此问题的过程。

1、前端页面传参

location.href = "${path}/AppFileDownload.action?file_path="+file_path+"&file_name="+encodeURI(encodeURI(file_name));

此处对文件名做了编码处理,此处解释一下为什么用两次encodeURI编码:

如果只进行一次encodeURI,得到的是UTF-8形式的URL,服务器端通过request.getParameter()解码查询参数(通常是iso-8859-1)就会得到乱码。

如果进行两次encodeURI,第一次编码得到的是UTF-8形式的URL,第二次编码得到的依然是UTF-8形式的URL,但是在效果上相当于首先进行了一次UTF-8编码(此时已经全部转换为ASCII字符),再进行了一次iso-8859-1编码,因为对英文字符来说UTF-8编码和ISO-8859-1编码的效果相同。在服务器端,首先通过request.getParameter()自动进行第一次解码(可能是gb2312,gbk,utf-8,iso-8859-1等字符集,对结果无影响)得到ascii字符,然后再使用UTF-8进行第二次解码,通常使用java.net.URLDecoder("","UTF-8")方法。

两次编码两次解码的过程为:

UTF-8编码->UTF-8(iso-8859-1)编码->iso-8859-1解码->UTF-8解码,编码和解码的过程是对称的,所以不会出现乱码。

假设页面端输入的中文是一个“中”,按照下面步骤进行解码

(1)第一次encodeURI,按照utf-8方式获取字节数组变成[-28,-72-83],对字节码数组进行遍历,把每个字节转化成对应的16进制数,这样就变成了[E4,B8,AD],最后变成[�,�,�]  此时已经没有了多字节字符,全部是单字节字符。

(2)第二次encodeURI,进行编码,会把%看成一个转义字符,并不编码%以后字符,会把%编码成%.把数组最后变成[�,�,�]然后就把处理后的数据[�,�,�]发往服务器端,
当应用服务器调用getParameter方法,getParameter方法会去向应用服务器请求参数
应用服务器最初获得的就是发送来的[�,�,�],应用服务器会对这个数据进行URLdecode操作,应用服务器进行解码的这一次,不管是按照UTF-8,还是GBK,还是ISO-8859,,都能得到[�,�,�],因为都会把%解析成%.并把这个值返回给getParameter方法

(3)再用UTF-8解码一次,就得到"中"了。

如果不编码两次,当服务器自动解码的时候,假如是按照ISO-8859去解码UTF-8编码的东西,就是会出现乱码。

2、服务端处理文件名乱码问题

@Override
	public String execute() throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String filePath = request.getParameter("file_path");
		String fileName = request.getParameter("file_name");
		// 获取要传递给客户端的文件数据
		ServletOutputStream outputStream = null;
		byte[] bytes = FastDFSUtil.download(filePath, fileName);
		// 解决浏览器中文乱码的问题
		if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) { 
			// 火狐
		    //解码一次
			fileName = java.net.URLDecoder.decode(fileName,"UTF-8");
			BASE64Encoder base = new BASE64Encoder();
			fileName = "=?utf-8?B?"+base.encode(fileName.getBytes("utf-8"))+"?=";
		} else if (request.getHeader("User-Agent").toUpperCase()
				.indexOf("MSIE") > 0) { 
			// IE浏览器
			fileName = URLEncoder.encode(fileName, "UTF-8");
		} else if (request.getHeader("User-Agent").toUpperCase()
				.indexOf("CHROME") > 0) { 
			// 谷歌
			fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
		}

		// 设置响应头, 响应为下载,下载的文件名是什么
		response.addHeader("Content-Disposition", "attachment; filename="+ fileName);
		response.setContentType("application/octet-stream");
		response.setHeader("Pragma", "public");
		response.setHeader("Cache-Control", "max-age=0");
		try {
			outputStream = response.getOutputStream();
			outputStream.write(bytes);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				outputStream.flush();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值