一、初步了解
先看代码
public class URLEncodeTest { public static void main(String[] args) throws UnsupportedEncodingException { //将application/x-www-form-urlencoded字符串转换成普通字符串 String keyWord = URLDecoder.decode("%E5%BC%80%E5%8F%91%E6%B5%8B%E8%AF%95_test44444", "UTF-8"); System.out.println(keyWord); //将普通字符串转换成application/x-www-form-urlencoded字符串 开发测试_test44444 String urlStr = URLEncoder.encode("开发测试_test44444" , "UTF-8"); System.out.println(urlStr); } }
结果如下:
开发测试_test44444 %E5%BC%80%E5%8F%91%E6%B5%8B%E8%AF%95_test44444
URLDecoder类包含一个decode(String s,String charcter)静态方法,它可以将看上去乱码的特殊字符串转换成普通字符串。
URLEncoder类包含一个encode(String s,String charcter)静态方法,它可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串。
二、文件下载时文件名为什么要用URLEncoder编码
如果不使用URLEncoder进行编码,代码如下:
// response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setHeader("content-disposition", "attachment;filename=" + fileName);
效果如下:
content-disposition: attachment;filename=????_test44444.txt
原因分析:当URL地址中仅包含普通非中文字符串和application/x-www-form-urlencoded MIME字符串无须转换,而包含中文字符串的普通字符串则需要转换,换句话说,也就是说URL地址中有"中文字符串"传递时,才会考虑用到上面提到的两个类,这样就可以将传递过来的中文接受后,再还原成原来的中文字符串.如不转换,则通过URL传递过来的中文字符中会变成乱码,无法还原了。同样,响应头中存在中文字符串时也一样。
所以,在后端用URLEncoder编码,然后在前端解码
后端编码
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
前端解码
//从响应头获取文件名 export function getFileNameFromHeader(response) { const disposition = response.headers["content-disposition"] let fileName = disposition.substring(disposition.indexOf("filename=") + 9); if (window.navigator.userAgent.indexOf("Firefox") > -1) { fileName = fileName.substring(fileName.indexOf("-8?B?") + 5, fileName.indexOf("?=")) fileName = base64Util.decode(fileName); } else { fileName = decodeURIComponent(fileName); } return fileName }
前端进行编码和解码的方法:
/** * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI). * @param encodedURIComponent A value representing an encoded URI component. */ declare function decodeURIComponent(encodedURIComponent: string): string; /** * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ declare function encodeURIComponent(uriComponent: string | number | boolean): string;
三、应用场景
1、所有的GET请求
2、网址中有中文等情况
3、POST请求,所有的Key和Value在提交之前都要经过URLEncoder
例子:请求拦截器中对请求体的value进行编码,然后再拼接到url中。
service.interceptors.request.use( config => { if (store.getters.token) { config.headers['Authorization'] = store.getters.token } // params参数编码 let url = config.url; if (config.params) { url += '?'; let keys = Object.keys(config.params); for (let key of keys) { if (config.params[key] !== null && config.params[key] !== "") { url += `${key}=${encodeURIComponent(config.params[key])}&`; } } url = url.substring(0, url.length - 1); config.params = {}; } config.url = url; return config; }, error => { console.log(error) // for debug Promise.reject(error) } )
springboot的自带的过滤器会将前端编码过的中文字符串进行解码。