◉◡◉ 您好,欢迎到访伊成个人站!

base64出现空格问题的解决方案

本文于1655天之前发表,文中内容可能已经过时。

使用背景

项目中有一个参数是 byte[],在构建 http请求的时候不便参数的传输,于是就想到了 使用base64进行编码之后当成字符串进行传输。

接下来就用自己写了一个http工具类,代码如下(片段):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

/**
* 参数方式post发送 .
*
* @param simpleHttpRequest 请求
* @return 响应
*/
public static SimpleHttpResponse post(SimpleHttpRequest simpleHttpRequest) {
try {
HttpClient httpClient = buildHttpClient(simpleHttpRequest);
PostMethod method = new PostMethod(simpleHttpRequest.getUrl());
method.addRequestHeader("Connection", "close"); // 服务端应答完毕自动关闭连接
method.addRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (simpleHttpRequest.getHttpHeader() != null) {
for (Map.Entry<String, String> entry : simpleHttpRequest.getHttpHeader().entrySet()) {
method.addRequestHeader(entry.getKey(), entry.getValue());
}
}
if (simpleHttpRequest.getParams() != null && simpleHttpRequest.getParams().size() > 0) {
NameValuePair[] nameValuePairs = new NameValuePair[simpleHttpRequest.getParams().size()];
int i = 0;
for (Map.Entry<String, Object> entry : simpleHttpRequest.getParams().entrySet()) {
nameValuePairs[i++] = new NameValuePair(entry.getKey(), (String) entry.getValue());
}
method.addParameters(nameValuePairs);
String content = StringUtils.parseMapToParamsStr(simpleHttpRequest.getParams());
RequestEntity requestEntity = new ByteArrayRequestEntity(content.getBytes("UTF-8"));
method.setRequestEntity(requestEntity);
}

int status = httpClient.executeMethod(method);
String response = null;
if (status == HttpStatus.SC_OK) {
response = method.getResponseBodyAsString();
}

return new SimpleHttpResponse(status, response);
} catch (HttpException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}

}

项目启动之后,参数都传递过去了,没什么毛病。但是呢,会出现一个问题,byte[] 用base64编码之后可能会出现一些 “+” 加号,使用自定义的 httpUtils 请求的时候,会把 “+” 变成空格。

使用base64编码之后的 byte[]字符串

1
2
3
XRxZSKo4/oSH1tHOKOzYbFigK0Nq5vJP3RKSsPA8y9EplsdMMZTv+jW94v7bcU/28eaM6u1I9MSE
sWFrs5JrhyXqvpztMxk6y/77qR7RuClpp4A+TXOyCdHKsA/aGxluA6gsvuQaDSHNNQ1pWBzsKlds
lMDtF1IGCRQJSyzxtnU=

使用httpUtils 获取的 byte[] 字符串

1
2
3
XRxZSKo4/oSH1tHOKOzYbFigK0Nq5vJP3RKSsPA8y9EplsdMMZTv jW94v7bcU/28eaM6u1I9MSE
sWFrs5JrhyXqvpztMxk6y/77qR7RuClpp4A TXOyCdHKsA/aGxluA6gsvuQaDSHNNQ1pWBzsKlds
lMDtF1IGCRQJSyzxtnU=

问题的原因找到了,那接下来如何解决呢?

解决方案

解决方案 一

将加密后的空格全部替换为 ‘+’ 号,replace(“ “, “+”);

或者,将将加密后的字符串替换为 “%2B”, 再将 “%2B”替换回 ‘+’ 号,replace(“%2B”, “+”)

解决方案 二

使用 post方式提交的时候,参数为 json形式。

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* post请求 json参数
* @param url 请求地址
* @param params json参数
* @return
*/
public static String doPost(String url, JSONObject params){
String strResult = "";
// 1. 获取默认的client实例
CloseableHttpClient client = HttpClients.createDefault();
// 2. 创建httppost实例
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
try {
httpPost.setEntity(new StringEntity(params.toJSONString(),"utf-8"));
CloseableHttpResponse resp = client.execute(httpPost);
try {
// 7. 获取响应entity
HttpEntity respEntity = resp.getEntity();
strResult = EntityUtils.toString(respEntity, "UTF-8");
} finally {
resp.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return strResult;
}

使用 post请求json参数这个方法,具体代码:

1
2
3
4
5
6
String url = "http://127.0.0.1:8080/v1/auth";
JSONObject params = new JSONObject();
params.put("type",String.valueOf(userType));
params.put("data",encodeData);
params.put("user",userName);
String responseBody = HttpUtils.doPost(url, params);

以上两种解决方法,均可以解决这个问题。

base64编码,解码我用的是 sun.misc.BASE64Decoder
开始我还以为 切换成 其他的 base64 类库就不会有这个问题,我尝试了Apache Commons Codec的Base64 然后编码出来的字符串是一样的。

纯属工作笔记记录,如有错误,烦请指出!

支付宝打赏 微信打赏