在很多spring mvc的vm页面中,对于上传的中文文件,保存在数据库和通过java代码取出来渲染到vm页面都不会有乱码的问题,因为数据库一般是gbk编码,vm页面也一般是gbk编码:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
</head>
这样显示是不会有乱码问题的,但是如果把这个渲染出来的中文文件文件名作为url的post或者超链接参数时,由于要对url中传递的参数进行编码,这个时候就会出乱码的问题,此时就可以采用传参时编码,然后在后台得到请求参数时解码的方式进行:
JavaScript encodeURIComponent(URIString) 函数可把字符串作为 URI 组件进行编码。参数必须是一个字符串,含有 URI 组件或其他要编码的文本。返回值中某些字符将被十六进制的转义序列进行替换。
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
注意:
encodeURIComponent() 函数 与 encodeURI() 函数的区别之处,前者假定它的参数是 URI 的一部分(比如协议、主机名、路径或查询字符串)。因此 encodeURIComponent() 函数将转义用于分隔 URI 各个部分的标点符号。
例子:
<script type="text/javascript"> document.write(encodeURIComponent("http://www.w3school.com.cn")) document.write("<br />") document.write(encodeURIComponent("http://www.w3school.com.cn/p 1/")) document.write("<br />") document.write(encodeURIComponent(",/?:@&=+$#")) </script>
编码后:
http%3A%2F%2Fwww.w3school.com.cn http%3A%2F%2Fwww.w3school.com.cn%2Fp%201%2F %2C%2F%3F%3A%40%26%3D%2B%24%23
下面是一个完成前后台编码和解码防止请求中含有中文或者特殊字符乱码的例子:
1.前台post请求的时候对发送的数据进行encodeURIComponent()编码:
var riskLevel= $("#riskLevelId").attr("value"); var riskDesprition=encodeURIComponent($("#riskDescriptionId").html()); var modifySuggest=encodeURIComponent($("#modifySuggest").val()); $.post( "${path}/executeSaveOperate.action", {"riskLevel":riskLevel,"riskDesprition":riskDesprition,"modifySuggest",modifySuggest}, function(data){ if(data=='1'){ alert("保存成功!"); }else{ alert("保存失败!"); } });
后台:用UTF-8转译:
String riskLevel = URLDecoder.decode(request.getParameter("riskLevel"),
"UTF-8");
String riskDesprition = URLDecoder.decode(
request.getParameter("riskDesprition"), "UTF-8");
String modifySuggest = URLDecoder.decode(
request.getParameter("modifySuggest"), "UTF-8");
即可解决jQuery post请求中文乱码问题。
一:但是ava.net.URLEncoder编码特点:
这样有一个小问题,就是在解码的时候由于采用的是java的一个类java.net.URLEncoder,
这个类是把一个string转换为application/x-www-form-urlencoded
MIME 的格式,他的解码方式是:1.'a'--'z','A'--'Z'和'0'--'9'保持原样 。
2. 特殊字符:".
", "-
", "*
"和"_"保持原样。
3. 空格 " "被转换成一个加号 "+"。
4. 所有的其他字符包括汉字,被首先转换成字节数组,然后每一个字节以三字符形式表示的十六进制方式“%xy”,其中xy是2个数字形式的十六进制表现方式,建议是用“UTF-8”进行编码,如果没有指定,就以默认方式编码。
例如:"The string ü@foo-bar"编码后为: "The+string+%C3%BC%40foo-bar"
ü is 编码为两字节的 C3 (hex) and BC (hex)。
所以,含有空格的字符串进行编码和解码时就多了一个“+”号,而“+”号在html页面中时不能解析转码的 ,所以在下载中文文件时为了文件名不乱码,需要特殊处理下:
response.setContentType("application/x-msdownload;charset='UTF-8'");
//html页面不能把utf解析出的"+"号进行转码,也就是不识别+号,所以要进行转码
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(("riskm_"
+ arkUser+"_" + fileName), "UTF-8").replaceAll("\\+", "%20"));
URLEncoder一般是在java代码中,也就是后天进行编码,这样通过response把数据发送到客户端进行解码是就不会乱码,比如说下载文件时,文件名是中文,有空格,点击下载时,在弹出的windows保存框中的文件名就是通过服务器response发送过来的,如果不进行编码直接发送过来有时就会出现乱码的情况。
这种编码方式, 在URL中使用的字符就必须是一个ASCII字符集的固定字集中的元素。
/ & ? @ # ; $ + = 和 %也可以被使用,但是它们各有其特殊的用途,如果一个文件名包括了这些字符( / & ? @ # ; $ + = %),这些字符和所有其他字符就应该被编码。
例子1:
这段代码对其进行编码:
String query = URLEncoder.encode( "pg=q&kl=XX&stype=stext&q=+\"Java+I/O\"&search.x=38&search.y=3");System.out.println(query);
不幸的是,得到的输出是:
pg%3Dq%26kl%3DXX%26stype%3Dstext%26q%3D%2B%22Java%2BI%2FO%22%26search.x%3D38%26search.y%3D3
出现这个问题就是方法URLEncoder.encode( ) 在进行盲目地编码。它不能区分在URL或者查询string中被用到的特殊字符(象前面string中的“=”,和“&”)和确实需要被编码的字符。由此,所以URL需要像下面这样一次只编码一块:
String query = URLEncoder.encode("pg");
query += "=";
query += URLEncoder.encode("q");
query += "&";
query += URLEncoder.encode("kl");
query += "=";
query += URLEncoder.encode("XX");
query += "&";
query += URLEncoder.encode("stype");
query += "=";
query += URLEncoder.encode("stext");
query += "&";
query += URLEncoder.encode("q");
query += "=";
query += URLEncoder.encode("\"Java I/O\"");
query += "&";
query += URLEncoder.encode("search.x");
query += "=";
query += URLEncoder.encode("38");
query += "&";
query += URLEncoder.encode("search.y");
query += "=";
query += URLEncoder.encode("3");
System.out.println(query);
这才是你真正想得到的输出:
pg=q&kl=XX&stype=stext&q=%2B%22Java+I%2FO%22&search.x=38&search.y=3
例子2:
一个QueryString类。在一个java对象中,它使用了类URLEncoder来编码连续的属性名和属性值对,这个java对象被用来发送数据到服务器端的程序。
当你在创建一个QueryString对象时,你可以把查询string中的第一个属性对传递给类QueryString的构造函数,得到初始string。如果要继续加入后面的属性对,就应调用方法add(),它也能接受两个string作为参数,能对它们进行编码。方法getQuery( )返回一个属性对被逐个编码后得到的整个string。
Example :The QueryString class
package com.macfaq.net;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
public class QueryString {
private StringBuffer query = new StringBuffer();
public QueryString(String name, String value) {
encode(name, value);
}
public synchronized void add(String name, String value) {
query.append('&');
encode(name, value);
}
private synchronized void encode(String name, String value) {
try {
query.append(URLEncoder.encode(name, "UTF-8"));
query.append('=');
query.append(URLEncoder.encode(value, "UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Broken VM does not support UTF-8");
}
}
public String getQuery() {
return query.toString();
}
public String toString() {
return getQuery();
}
}
利用这个类,现在我们就能对前面那个例子中的string进行编码了:
QueryString qs = new QueryString("pg", "q");
qs.add("kl", "XX");
qs.add("stype", "stext");
qs.add("q", "+\"Java I/O\"");
qs.add("search.x", "38");
qs.add("search.y", "3");
String url = "http://www.altavista.com/cgi-bin/query?" + qs;
System.out.println(url);
二:
与URLEncoder 类相对应的URLDecoder 类有两种静态方法。它们解码以x-www-form-url-encoded这种形式编码的string。也就是说,它们把所有的加号(+)转换成空格符,把所有的%xx分别转换成与之相对应的字符:
public static String decode(String s) throws Exception
public static String decode(String s, String encoding) // Java 1.4 throws UnsupportedEncodingException
第一种解码方法在java1.3和java1.2中使用。第二种解码方法在java1.4和更新的版本中使用。最好选择UTF-8解码。它比其他任何的编码形式更有可能得到正确的结果。
如果string包含了一个“%”,但紧跟其后的不是两位16进制的数或者被解码成非法序列,该方法就会抛出IllegalArgumentException 异常。当下次再出现这种情况时,它可能就不会被抛出了。这是与运行环境相关的,当检查到有非法序列时,抛不抛出IllegalArgumentException 异常,这时到底会发生什么是不确定的。在Sun's JDK 1.4中,不会抛出什么异常,它会把一些莫名其妙的字节加进不能被顺利编码的string中。这可能就是一个安全漏洞。
由于这个方法没有触及到非转义字符,所以你可以把整个URL作为参数传给该方法,不用像之前那样分块进行。例如:
String input = "http://www.altavista.com/cgi-bin/" + "query? pg=q&kl=XX&stype=stext&q=%2B%22Java+I%2FO%22&search.x=38&search.y=3";
try {
String output = URLDecoder.decode(input, "UTF-8");
System.out.println(output);
}