最近使用httpclient上传图片并伴有中文其他字段参数,然后,传输过去后,中文显示???乱码问题
//调用方法
public static ResultHik createVisitor(String accessToken, MdVisitor mdVisitor) throws DeviceException {
byte[] faceVerify = mdVisitor.getVerifyFace();
mdVisitor.setVerifyFace(null);
log.info("调用魔点api: 创建访客授权 init accessToken:{};mdVisitor:{}", accessToken, JSON.toJSONString(mdVisitor));
String uri = MdConstant.createVisitor(accessToken);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//重点:::::之前没有,解决问题的点,需要增加需要传中文的格式设置UTF-8格式
ContentType contentType = ContentType.create("multipart/form-data",StandardCharsets.UTF_8);
builder.setContentType(contentType);
//识别人脸图片
builder.addBinaryBody("verifyFace", faceVerify, ContentType.MULTIPART_FORM_DATA, mdVisitor.getVisitorMobile() + ".jpg");
//传中文
builder.addTextBody("visitorName", mdVisitor.getVisitorName(), contentType);
builder.addTextBody("visitorMobile", StringUtils.leftPad(mdVisitor.getVisitorMobile(), 11, "1"), ContentType.MULTIPART_FORM_DATA);
builder.addTextBody("startTime", JSON.toJSONString(mdVisitor.getStartTime()), ContentType.MULTIPART_FORM_DATA);
builder.addTextBody("endTime", JSON.toJSONString(mdVisitor.getEndTime()), ContentType.MULTIPART_FORM_DATA);
//传中文
builder.addTextBody("address", JSON.toJSONString(mdVisitor.getAddress()), contentType);
builder.addTextBody("ids", StringUtils.join(mdVisitor.getPermitDeviceIds(), ","), ContentType.MULTIPART_FORM_DATA);
String resCtx = HttpHelper.doUploadImageHttp(RequestType.POST, uri, builder);
ResultHik bean = new Gson().fromJson(resCtx, new TypeToken<ResultHik>() {}.getType());
return bean;
}
//执行方法
public static String sendUploadHttp(RequestType reqType, String url, Map<String, String> headers,
MultipartEntityBuilder builder) throws DeviceException {
HttpRequestBase reqBase = reqType.getHttpType(url);
log.info("--->>开始向地址[{}]发起 [{}] 上传图片请求", url, reqBase.getMethod());
log.info("--->>请求头为{}", JSON.toJSONString(headers));
log.info("--->>请求参数为{}", JSON.toJSONString(builder));
long startTime = System.currentTimeMillis();
CloseableHttpClient httpClient = getHttpClient();
//设置请求url
config(reqBase);
//已经设置了,防止中文乱码,但是为什么还有乱码问题
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
HttpEntity build = builder.build();
((HttpEntityEnclosingRequest) reqBase).setEntity(build);
//响应对象
CloseableHttpResponse res = null;
//响应内容
String resCtx = null;
try {
//执行请求
res = httpClient.execute(reqBase);
log.info("--->>执行请求完毕,响应状态:{}", res.getStatusLine());
if (res.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new DeviceException("--->>HTTP访问异常:" + res.getStatusLine());
}
//获取请求响应对象和响应entity
HttpEntity httpEntity = res.getEntity();
if (httpEntity != null) {
resCtx = EntityUtils.toString(httpEntity, "utf-8");
log.info("--->>获取响应内容:{}", resCtx);
}
} catch (Exception e) {
throw new DeviceException("请求失败", e);
} finally {
if (res != null) {
try {
res.close();
} catch (IOException e) {
throw new DeviceException("--->>关闭请求响应失败", e);
}
}
}
long endTime = System.currentTimeMillis();
log.info("--->>请求执行完毕,耗费时长:{} 秒", (endTime - startTime) / 1000);
return resCtx;
}
其实在执行代码中已经有了解决中文乱码问题,
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
那为什么还是会乱码,咱么一起看看源码
//增加参数,我们在传文件和其他参数都会用到ContentType.MULTIPART_FORM_DATA
builder.addTextBody("address", JSON.toJSONString(mdVisitor.getAddress()), ContentType.MULTIPART_FORM_DATA);
//MultipartEntityBuilder类
//addTextBody方法
public MultipartEntityBuilder addTextBody(
final String name, final String text, final ContentType contentType) {
return addPart(name, new StringBody(text, contentType));
}
//去看看ContentType的MULTIPART_FORM_DATA怎么处理的
//ContentType类,用的是ISO_8859_1格式,就是这个问题
public static final ContentType MULTIPART_FORM_DATA = create("multipart/form-data", Consts.ISO_8859_1);
//我们再去看下MultipartEntityBuilder类buildEntity方法
MultipartFormEntity buildEntity() {
String boundaryCopy = boundary;
if (boundaryCopy == null && contentType != null) {
boundaryCopy = contentType.getParameter("boundary");
}
if (boundaryCopy == null) {
boundaryCopy = generateBoundary();
}
Charset charsetCopy = charset;
if (charsetCopy == null && contentType != null) {
charsetCopy = contentType.getCharset();
}
final List<NameValuePair> paramsList = new ArrayList<NameValuePair>(2);
paramsList.add(new BasicNameValuePair("boundary", boundaryCopy));
if (charsetCopy != null) {
paramsList.add(new BasicNameValuePair("charset", charsetCopy.name()));
}
final NameValuePair[] params = paramsList.toArray(new NameValuePair[paramsList.size()]);
final ContentType contentTypeCopy = contentType != null ?
contentType.withParameters(params) :
ContentType.create("multipart/" + DEFAULT_SUBTYPE, params);
//参数获取
final List<FormBodyPart> bodyPartsCopy = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) :
Collections.<FormBodyPart>emptyList();
final HttpMultipartMode modeCopy = mode != null ? mode : HttpMultipartMode.STRICT;
final AbstractMultipartForm form;
switch (modeCopy) {
case BROWSER_COMPATIBLE:
//mode我们使用的是这个模式,我们传入的参数bodyPartsCopy
form = new HttpBrowserCompatibleMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
break;
case RFC6532:
form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, bodyPartsCopy);
break;
default:
form = new HttpStrictMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
}
return new MultipartFormEntity(form, contentTypeCopy, form.getTotalLength());
}
//在看下HttpBrowserCompatibleMultipart对bodyPartsCopy的处理
public HttpBrowserCompatibleMultipart(
final Charset charset,
final String boundary,
final List<FormBodyPart> parts) {
super(charset, boundary);
//直接使用传入的参数
this.parts = parts;
}
//最后,我们使用的参数还是格式,
//所以关键的地方,要自己设置ContentType,并传需要的参数
😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥