最近新做了一个需求,需要通过https远程调用第三方接口。之前也对接过一些接口,只不过之前对接的接口的报文编码格式基本上都是UTF-8,而这次对接的是GBK。
一顿操作之后和对端的接口终于通了,不过却发现对方返回的报文出现一堆问号乱码。开始以为底层的实现没有做URLDecoder(实际上即使没做也不应该出现问号乱码),后面尝试了下发现不是这个原因。于是考虑可能是接收报文处理的地方没有使用正确的编码格式。
我们这边的处理应答码报文的工具类大概如下:
public class ResponseHandlerHelper {
private Charset defaultCharset = StandardCharsets.UTF_8;
public ResponseHandlerHelper() {
}
public ResponseHandlerHelper(Charset defaultCharset) {
this.defaultCharset = defaultCharset;
}
public HttpEntity processResponse(HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
// 这里获取编码格式
Charset responseCharset = getResponseCharset(entity);
String result = EntityUtils.toString(entity, responseCharset);
throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase() + ':' + result);
}
return entity;
}
public Charset getResponseCharset(HttpEntity entity) {
ContentType contentType = ContentType.getOrDefault(entity);
// 如果应答码报文没有指定编码格式,则使用默认的UTF-8
Charset charset = contentType.getCharset();
if (charset == null) {
charset = defaultCharset;
}
return charset;
}
public File copy(InputStream content, File targetFile) throws IOException {
try (BufferedInputStream inStream = new BufferedInputStream(content); OutputStream out = new BufferedOutputStream(new FileOutputStream(targetFile))) {
byte[] buffer = new byte[8192];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
return targetFile;
}
}
}
注意代码中加注释的地方。 找到原因:对方返回报文未指定编码格式导致使用了默认的UTF-8格式解码导致。
其实到这里已经知道如何解决,就是自己指定默认的编码格式为GBK。不过想到之前有收藏过一张乱码原因的图,回头看了下有一个场景和这个正好相符(以GBK写中文UTF-8读)。这里贴出来,方便后续快速定位问题。