一、问题描述
项目中,使用restTemplate上传文件,当文件名包含中文名,通过restTemplate.postForObject调用接口上传时,比如测试文件.doc会变成????.doc
二、解决方案
这里有两种方案,一种是将spring升级,升级到spring5.x,另一种是自定义converter,下面我们详解一下第二种方案
1.复制FormHttpMessageConverter类下的所有代码,新建UploadFileFormHttpMessageConverter类

2.修改getAsciiBytes方法

3.新建UploadRestTemplateUtil,替换新的converter
public class UploadRestTemplateUtil {
/**
* 获取上传文件的restTemplate
* @return
*/
public static RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
messageConverters.add(new MappingJackson2HttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.ALL);
for (int i = 0; i < messageConverters.size(); i++) {
HttpMessageConverter<?> converter = messageConverters.get(i);
if (converter instanceof StringHttpMessageConverter) {
messageConverters.remove(i);
messageConverters.add(i, stringHttpMessageConverter);
}
if (converter instanceof MappingJackson2HttpMessageConverter) {
try {
((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
} catch (Exception e) {
e.printStackTrace();
}
}
if (converter instanceof FormHttpMessageConverter) {
// 针对文件上传文件名乱码情况使用自定义的converter
UploadFileFormHttpMessageConverter myConverter = new UploadFileFormHttpMessageConverter();
myConverter.setCharset(StandardCharsets.UTF_8);
messageConverters.remove(i);
messageConverters.add(i, myConverter);
}
}
return restTemplate;
}
}
4.使用
UploadRestTemplateUtil.getRestTemplate()
三、分析
跟进到restTemplate中,先看doExecute方法

很明显 request.execute是在发送请求,那么我们看一下在请求被发送之前,到底做了些什么操作。也就是requestCallback.doWithRequest(request)这行代码。跟进去:
发现是一个内部类——HttpEntityRequestCallback:最终走到而是下面的这一行代码:

继续跟进,发现getAsciiBytes方法硬编码了

这里使用了US-ASCII编码,肯定会发生乱码,这个应该是一个bug,所以将spring升级也可以解决。

本文针对使用RestTemplate上传文件时遇到的中文名乱码问题进行分析和解决,提供了一种自定义converter的方法,包括复制FormHttpMessageConverter,修改getAsciiBytes方法,创建UploadRestTemplateUtil并替换新converter的步骤。
1298

被折叠的 条评论
为什么被折叠?



