最近在用httpclient获取服务器上文件的文件名时,当文件名是中文时乱码。乱码的话,肯定是编解码集不一致导致的。
通常咱们在使用HttClient进行文件下载时,须要获取到文件的名称及类型,可是不少时候提供给咱们的url中是不包含这些信息的,因此须要经过HttpResponse中的信息来获取这些。code
将上面下载时获取的response做为参数进行传递。
/**
* 获取response header中Content-Disposition中的filename值
* @param response
* @return
*/
private String getFileName(HttpResponse response) {
Header contentHeader = response.getFirstHeader("Content-Disposition");
String filename = UUID.randomUUID().toString().replace("-","");
if (contentHeader != null) {
HeaderElement[] values = contentHeader.getElements();
if (values.length == 1) {
NameValuePair param = values[0].getParameterByName("filename");
if (param != null) {
try {
String code1 = "windows-1252";
String code2 = "ISO-8859-1";
String name = param.getValue();
//判断如今的编码格式
if(name.equals(new String(name.getBytes(code1),code1))){
//GBK为铁塔在Content-Disposition中filename使用的编码格式
filename = new String(name.getBytes(code1), "GBK");
if(!EncodeUtils.isLetterDigitOrChinese(filename)){
filename=URLDecoder.decode(param.getValue(),"utf-8");
}
}else if(name.equals(new String(name.getBytes(code2),code2))){
filename = new String(name.getBytes(code2), "GBK");
if(!EncodeUtils.isLetterDigitOrChinese(filename)){
filename=URLDecoder.decode(param.getValue(),"utf-8");
if(!EncodeUtils.isLetterDigitOrChinese(filename)){
filename=URLDecoder.decode(param.getValue(),"utf-8");
}
}
}
//filename = param.getValue();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return filename;
}
通常咱们获取到的信息,若是没有进行特殊处理,都是默认的ISO-8859-1编码格式的,可是在windows10的系统下,有时会将ISO-8859-1编码认为是window-1252进行传递(这也是个坑)。这样就会致使在进行解码时,解出来的仍是乱码。blog
这里我针对传递的参数通过了GBK编码和普通编码的处理,不针对全部的乱码都能解决,可是对一些按照正常解码方式还没法进行解码的能够尝试用这种方式进行解码。
通常的解码方式:filename = URLDecoder.decode(param.getValue(),"UTF-8");
或者:filename = new String(param.getValue().getBytes(),"UTF-8");
上面的isLetterDigitOrChinese:是我自定义的一个判断解析后的文件名是否符合要求的正则。
/** 判断是否只包含数字,字母,汉字和英文的(),.,-,_ 和中文的()**/
public static boolean isLetterDigitOrChinese(String str) {
String regex = "^[a-z_0-9A-Z-.()()\u4e00-\u9fa5]+$";//其余须要,直接修改正则表达式就好
return str.matches(regex);
}
上面一段是百度的,但是还是没有解决问题。那就只能自己解决问题了。
乱码,首先要知道字符的原来编码,以及现在的编码,这样问题就迎刃而解了。
推荐一个网站,乱码猜测,识别原来乱码的字符编码集
http://www.mytju.com/classcode/tools/messyCodeRecover.asp
通过上面的结果,我们就能知道字符编码格式,再进行编码。问题就解决了
这里我项目HttpClient原来的编码是IOS_8859_1,现在的编码格式是UTF-8
HttpGet httpget = new HttpGet(url);
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
//配置请求的超时设置
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(10000)
.setSocketTimeout(10000).build();
httpget.setConfig(requestConfig);
CloseableHttpResponse response = httpclient.execute(httpget);
Header contentHeader = response.getFirstHeader("Content-Disposition");
HeaderElement[] elements = contentHeader.getElements();
HeaderElement[] values = contentHeader.getElements();
NameValuePair filename = values[0].getParameterByName("filename");
String name = new String(filename.getValue().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);