情况是这样,在项目用调用文件服务的文件上传接口,出现存储的文件名显示为问号。
排查下:
- 直接postman调用上传接口,中文显示正常。
- 项目编码为utf8。
- 项目解析文件名,打印控制台,正常显示。
- 查看form对象内容,已经是乱码情况。
RestTemplate内部有HttpMessageConverter接口,用于内容的转码,各种类型内容有不同的实现类。这些转换类默认编码有可能不是utf8的。
做了如下调整:
@Bean(name = "restUpload")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
for (Iterator<HttpMessageConverter<?>> iterator = list.iterator(); iterator.hasNext(); ) {
HttpMessageConverter item = iterator.next();
if (item instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) item).setDefaultCharset(StandardCharsets.UTF_8);
} else if (item instanceof FormHttpMessageConverter) {
((FormHttpMessageConverter) item).setCharset(StandardCharsets.UTF_8);
((FormHttpMessageConverter) item).setMultipartCharset(StandardCharsets.UTF_8);
}
}
restTemplate.setMessageConverters(list);
return restTemplate;
}
对于更改HttpMessageConverter后还是会出现乱码,我是直接使用一个笨方法,转成multipartFile进行发送,但是需要接收文件的服务进行解码显示(目前还没有深入去查明问题)。
HttpHeaders requestHeaders = uploadUtility.setHeaders();
MultiValueMap<String, Object> form = uploadUtility.getMultiValueMap(files);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, requestHeaders);
ResponseEntity<String> rss = restTemplate.exchange(uploadUrl, HttpMethod.POST, requestEntity, String.class);
public MultiValueMap<String, Object> getMultiValueMap(List<MultipartFile> files) throws IOException {
MultiValueMap<String, Object> multipartFile = new LinkedMultiValueMap<String, Object>();
for (MultipartFile file : files) {
File tempFile = multipartToFile(file);
FileSystemResource fileSystemResource = new FileSystemResource(tempFile);
multipartFile.add("file", fileSystemResource);
}
return multipartFile;
}
private File multipartToFile(MultipartFile multfile) throws IOException {
File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") +
multfile.getOriginalFilename());
multfile.transferTo(tmpFile);
return tmpFile;
}
文件服务获取文件名
MimeUtility.decodeText(file.getOriginalFilename());
有些包需要引用
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.4.4</version>
</dependency>
如上调整后,中文名显示为问号的问题得以解决。当然看起来这个解决方案并不是很完美。