浏览器下载中文乱码问题目
BASE64编码方式
base64的编解码方式
public static void main(String[] args) throws Exception {
String str = "这是需要BASE64编码的内容";
// 创建一个BASE64编码
BASE64Encoder base64Encoder = new BASE64Encoder();
//执行base64编码操作
String encode = base64Encoder.encode(str.getBytes("UTF-8"));
System.out.println(encode);
// 6L+Z5piv6ZyA6KaBQkFTRTY057yW56CB55qE5YaF5a65
//创建一个base64解码器
BASE64Decoder base64Decoder = new BASE64Decoder();
//执行base64解码操作
byte[] bs = base64Decoder.decodeBuffer(encode);
String context = new String(bs,"UTF-8");
System.out.println(context);//这是需要BASE64编码的内容
}
不同浏览器下载文件名中文乱码问题
IE和谷歌
关键代码
// 把中文名进行 UTF-8 编码操作。
String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");
// 然后把编码后的字符串设置到响应头中
response.setHeader("Content-Disposition", str)
实际操作
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1。获取要下载的文件名
String downloadName = "c.jpg";
//2.读取要下载的文件内容
ServletContext servletContext = getServletContext();
InputStream resourceAsStream = servletContext.getResourceAsStream("/photo/"+ downloadName);
//获取要下载的文件类型
String mimeType = servletContext.getMimeType("/photo/" + downloadName);
//4。在回传前,通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
//5。还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
String str = "attachment;fileName=" + URLEncoder.encode(downloadName,"UTF-8");
resp.setHeader("Content-Disposition", str);
//3。把下载的文件内容回传给客户端
ServletOutputStream outputStream = resp.getOutputStream();
IOUtils.copy(resourceAsStream, outputStream);
}
火狐浏览器乱码问题
火狐用的是BASE64的方式,需要对中文进行BASE64编码操作,同时修改响应头。
这时候需要把请求头 Content-Disposition: attachment; filename=中文名
编码成为:Content-Disposition: attachment; filename==?charset?B?xxxxx?=
=?charset?B?xxxxx?= 现在我们对这段内容进行一下说明。
=? 开始
charset 编码方式
B BASE64
xxxx 中文名
?= 结束
因为火狐使用的是 BASE64 的编解码方式还原响应中的汉字。所以需要使用 BASE64Encoder 类进行编码操作。
// 使用下面的格式进行 BASE64 编码后
String str = "attachment; fileName=" + "=?utf-8?B?"
+ new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";
// 设置到响应头中
response.setHeader("Content-Disposition", str)
实际操作
关键代码:
String str = "attachment;fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode(downloadName.getBytes()) + "?=";
resp.setHeader("Content-Disposition", str);
小结:
实际就是修改响应头的fileName,使得浏览器可以识别。
为提高复用性,可以这样写:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//1。获取要下载的文件名
String downloadName = "c.jpg";
//2.读取要下载的文件内容
ServletContext servletContext = getServletContext();
InputStream resourceAsStream = servletContext.getResourceAsStream("/photo/"+ downloadName);
//获取要下载的文件类型
String mimeType = servletContext.getMimeType("/photo/" + downloadName);
//4。在回传前,通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
//5。还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
String ua = req.getHeader("User-Agent");
if(ua.contains("Firefox")) {
String str = "attachment;fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode(downloadName.getBytes()) + "?=";
resp.setHeader("Content-Disposition", str);
}else {
String str = "attachment;fileName=" + URLEncoder.encode(downloadName,"UTF-8");
resp.setHeader("Content-Disposition", str);
}
// String str = "attachment;fileName=" + URLEncoder.encode(downloadName,"UTF-8");
// String str1 = "attachment;fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode(downloadName.getBytes()) + "?=";
//
// resp.setHeader("Content-Disposition", str);
//3。把下载的文件内容回传给客户端
ServletOutputStream outputStream = resp.getOutputStream();
IOUtils.copy(resourceAsStream, outputStream);
}