文章出处链接: http://www.devcheng.net/post/54aeaf8d.html
使用背景
项目中有一个参数是 byte[],在构建 http请求的时候不便参数的传输,于是就想到了 使用base64进行编码之后当成字符串进行传输。
接下来就用自己写了一个http工具类,代码如下(片段):
/**
* 参数方式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[]字符串
问题的原因找到了,那接下来如何解决呢?
解决方案
解决方案 一
将加密后的空格全部替换为 ‘+’ 号,replace(“ “, “+”);
或者,将将加密后的字符串替换为 “%2B”, 再将 “%2B”替换回 ‘+’ 号,replace(“%2B”, “+”)
解决方案 二
使用 post方式提交的时候,参数为 json形式。
具体代码如下:
/**
* 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参数这个方法,具体代码:
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 然后编码出来的字符串是一样的。
HTTP上传base64编码字符"+"变空格的问题
通过HTTP上传二进制数据可以先使用base64编码将二进制数据变成字符串上传,但是如果编码后的字符串含符号“+”,服务端接收到的就变成了空格,有一种解决的办法就是将base64字符串再调用UrlEncode编码,服务端解码就可以得到正确的数据
URLEncoder.encode(data)处理一下data数据即可