OKHttp header、post参数不支持中文的解决办法

来源:互联网 发布:网络写作软件哪个好 编辑:程序博客网 时间:2024/06/14 15:09

现象

项目在接入Okhttp请求框架的时候,发现当header或post参数中包含有中文的时候,都会报一个

Unexpected char xx at xx in xx value: xxx

这种格式的错误,下面把原因和解决办法分享给大家

原因

查看源码可以发现,不论你从什么入口设置header 或 post参数,Okhttp都会对其进行这样一段代码的检查

private void checkNameAndValue(String name, String value) {    if (name == null) throw new NullPointerException("name == null");    if (name.isEmpty()) throw new IllegalArgumentException("name is empty");    for (int i = 0, length = name.length(); i < length; i++) {        char c = name.charAt(i);        if (c <= '\u001f' || c >= '\u007f') {            throw new IllegalArgumentException(Util.format(                    "Unexpected char %#04x at %d in header name: %s", (int) c, i, name));        }    }    if (value == null) throw new NullPointerException("value == null");    for (int i = 0, length = value.length(); i < length; i++) {        char c = value.charAt(i);        if (c <= '\u001f' || c >= '\u007f') {            throw new IllegalArgumentException(Util.format(                    "Unexpected char %#04x at %d in %s value: %s", (int) c, i, name, value));        }    }}

而这也就使得当参数中含有中文时就会报错

解决办法

header参数

把使用 requestBuilder.header(name , value)的地方

替换成requestBuilder.header(name , getValueEncoded(value) )

方法代码如下:

//由于okhttp header 中的 value 不支持 null, \n 和 中文这样的特殊字符,所以这里//会首先替换 \n ,然后使用 okhttp 的校验方式,校验不通过的话,就返回 encode 后的字符串private static String getValueEncoded(String value) {    if (value == null) return "null";    String newValue = value.replace("\n", "");    for (int i = 0, length = newValue.length(); i < length; i++) {        char c = newValue.charAt(i);        if (c <= '\u001f' || c >= '\u007f') {            return URLEncoder.encode(newValue, "UTF-8");        }    }    return newValue;}

post参数

post参数可以通过将键值对转换为byte数组的形式来避免OKhttp的字符检查

requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),                getRequestData(postParams).toString().getBytes(“UTF-8”)));private static StringBuffer getRequestData(Map<String, String> params) {    StringBuffer stringBuffer = new StringBuffer();        try {        for (Map.Entry<String, String> entry : params.entrySet()) {            stringBuffer.append(entry.getKey()).append("=").append(entry.getValue()).append("&");        }        stringBuffer.deleteCharAt(stringBuffer.length() - 1);    //删除最后的一个"&"    } catch (Exception e) {        e.printStackTrace();    }    return stringBuffer;}

另外,这里比较重要的还有这句话:

MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"

此处如果没有charset=utf-8的话,服务端获取中文post参数可能会出现乱码

2 0
原创粉丝点击