今天在调试Tomcat 中servlet与浏览器之间传输数据,编码出错。
通过查阅资料,发现tomcat是以ISO8859-1方式对浏览器发送过来的数据进行解析,但是浏览器一般默认是以UTF-8的方式编码的,所以在传输中文的情况下可能会出现乱码,但是我的Firefox浏览器在接收数据之后,在servlet中没有经过处理也能正常显示,但是在IE上面却会乱码,在IE上只能通过设置编码方式进行处理。
我做了一个下载文件的servlet,起初是在Firefox文件名编码错误,IE上却没问题,后来做了改进,最终代码如下:
public class RPDemo01 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String filename = "广州地铁规划图.jpg"; String agent = req.getHeader("USER-AGENT"); //获取agent参数,IE有MSIE参数,FF没有该参数 if(agent != null && agent.indexOf("MSIE") == -1) {// FF 解决了ie和火狐中文乱码问题 ;猜测火狐检测到tomcat默认用iso8859-1编码 filename = new String(filename.getBytes("UTF-8"),"ISO8859-1");//先用utf-8编码成byte数组,然后用iso解码构成字符串 } else { // IE filename = URLEncoder.encode(filename,"UTF-8"); } resp.setHeader("content-disposition","attachment;filename="+filename); //以流的方式,将文件输出到浏览器中 InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../images/广州地铁规划图.jpg"); OutputStream os = resp.getOutputStream(); byte[] buf = new byte[1024]; int len = 0; while((len = is.read(buf))>0){ os.write(buf, 0, len); } os.close(); is.close(); } }
下面首先讨论Servlet接收浏览器数据:
我的Firefox 浏览器是无论服务器是否做了编码处理,都能正常显示中文,但是我在朋友的Firefox上面和在IE中没设置的情况下都是会乱码的,我猜测是我的Firefox这个版本检测到Tomcat服务器,自动把编码改成ISO8859-8然后在发送过去Servler中,所以不会产生乱码情况,大部分浏览器还是以UTF-8的编码方式发送数据。
通常有以下2种方式可以处理乱码问题
1,request.setCharacterEncoding("UTF-8"); 不过这种处理只有在接收POST(doPost)请求才会产生作用,GET方式无效
2,String username = req.getParameter("username");
username = new String(username.getBytes("ISO8859-1"),"UTF-8");
经过这种方式处理的可以解决浏览器发送数据乱码情况,无论GET方式还是POST方式都通用
现在轮到发送数据到服务器,response.setContentType("text/html;charset=UTF-8");这句代码只是通知浏览器用UTF-8编码,作用相当于HTML中的文档声明,
一般情况下用这种方式就可以解决浏览器的中文编码乱码问题,但是就像我上面的例子,文件下载的时候情况有所不同,IE要通过URLEncoder.encode(filename,"UTF-8");编码。
Firefox要通过new String(filename.getBytes("UTF-8"),"ISO8859-1")来解决,就是先用UTF-8解码文件名,再通过ISO8859-1编码在发送到浏览器才可正常解决(可能是我的Firefox版本不同,或者其他版本和IE一样的处理方式就可以了)。