解决浏览器下载中文乱码和URL中文乱码问题
下载中文乱码问题
中文乱码是个让人头痛的问题,这里整理针对下载时,中文乱码问题,下面是Java对应的实现,均已测试OK
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
// 关键代码
String fileName = HttpUtils.encodeAttachmentName(fileResponse.getOriginFileName(), request) ;
response.addHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setHeader("Accept-ranges", "bytes");
HttpUtils.encodeAttachmentName实现:
public static String encodeAttachmentName(String fileName , HttpServletRequest request) {
String enableFileName = fileName ;
try {
String userAgent = request.getHeader("User-Agent");
if(StringUtils.isBlank(userAgent)){
enableFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replace("+", "%20").replace("*", "%2A").replace("~", "%7E");
} else if (userAgent.indexOf("Firefox") > -1 ) {
// Firefox
enableFileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes(StandardCharsets.UTF_8)))) + "?=";
} else if (userAgent.indexOf("Safari") > -1 || userAgent.toUpperCase().indexOf("MSIE") > -1) {
// Safari Or IE
enableFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
} else {
// 其他浏览器
enableFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replace("+", "%20").replace("*", "%2A").replace("~", "%7E");
}
} catch (Exception e){
LOGGER.warn("Failed To encode file name", e);
throw new IllegalArgumentException("Failed To encode file name", e);
}
return enableFileName ;
}
注:
- 火狐浏览器Firefox,只支持
enableFileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes(StandardCharsets.UTF_8)))) + "?=";
这种方式; - Safari 浏览器,只支持
enableFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)
- Chrome 浏览器,可以支持
enableFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)
和enableFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
- 其他类型的浏览器,统一使用
URLEncoder.encode
的方式,这种方式可保证中文时不会出现乱码情况
URL路径中含有中文处理方式:
public static String uriEncode(String urlPath, String encoding) {
StringBuffer resultUri = new StringBuffer();
String[] keys = urlPath.split("/");
resultUri.append(urlEncode(keys[0], encoding));
for (int i = 1; i < keys.length; i++) {
resultUri.append("/").append(urlEncode(keys[i], encoding));
}
if (urlPath.endsWith("/")) {
// String#split ignores trailing empty strings,
// e.g., "a/b/" will be split as a 2-entries array,
// so we have to append all the trailing slash to the uri.
for (int i = urlPath.length() - 1; i >= 0; i--) {
if (urlPath.charAt(i) == '/') {
resultUri.append("/");
} else {
break;
}
}
}
return resultUri.toString();
}
/**
* Encode a URL segment with special chars replaced.
*/
public static String urlEncode(String url, String encoding) {
if (StringUtils.isBlank(url)) {
return "";
}
try {
String encoded = URLEncoder.encode(url, encoding);
return encoded.replace("+", "%20").replace("*", "%2A").replace("~", "%7E").replace("/", "%2F");
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Failed To Encode Uri", e);
}
}