关于rest:Spring RestTemplate带有utf-8文件名的POST文件

Spring RestTemplate POST file with UTF-8 filename

我正在使用Spring RestTemplate执行POST请求以发送PDF文件。 文件名包含一些UTF-8字符(例如é,è,à,ê、?)。

问题在于,发送请求后,在接收请求的另一侧,文件名没有预期的UTF-8字符,而我却拥有类似" popi?.pdf"的名称。

我试图在RestTemplate中显式设置UTF-8字符集,但仍然无法正常工作。

这是我的代码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public SomeThing storeFile(InputStream content, String fileName) {
    Charset utf8 = Charset.forName("UTF-8");
    RestTemplate restTemplate = new RestTemplate();

    HttpHeaders headersFile = new HttpHeaders();
    headersFile.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    headersFile.setContentDispositionFormData("file", fileName);
    List<Charset> listCharSet = new ArrayList<Charset>();
    listCharSet.add(utf8);

    headersFile.setAcceptCharset(listCharSet);

    InputStreamResource inputStreamResource = new InputStreamResource(content);
    HttpEntity<InputStreamResource> requestEntityFile = new HttpEntity<>(inputStreamResource, headersFile);

    MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
    multipartRequest.add("file", requestEntityFile);

    RestTemplate newRestTemplate = new RestTemplate();

    MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
    HttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
    newRestTemplate.getMessageConverters().add(0, stringHttpMessageConverter);
    newRestTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
    FormHttpMessageConverter convForm = new FormHttpMessageConverter();
    convForm.setCharset(utf8);
    newRestTemplate.getMessageConverters().add(convForm);

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.MULTIPART_FORM_DATA);
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multipartRequest, header);
    ResponseEntity<String> result = newRestTemplate.postForEntity(env.getProperty("core.endpoint") +"/documents", requestEntity, String.class);

}


根据rfc7578,当您发布包含多部分/表单数据的文件时,应使用"百分比编码"而不是文件名*

NOTE: The encoding method described in [RFC5987], which would add a
"filename*" parameter to the Content-Disposition header field, MUST NOT be used.

可以很容易地实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(0, new FormHttpMessageConverter() {
            @Override
            protected String getFilename(Object part) {
                if (part instanceof Resource) {
                    Resource resource = (Resource) part;
                    try {
                        return URLEncoder.encode(resource.getFilename(),"UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        return null;
                    }
                } else {
                    return null;
                }
            }
        });


很有可能尚未明确设置使用的JVM的文件编码的系统属性,与此同时,运行JVM的操作系统未使用UTF-8作为默认字符集。例如,如果JVM在Windows上运行,而我们未指定字符集,则默认值为Windows-1252。

您能否再次检查发送和接收文件的两个应用程序的JVM参数?在指定主类名称之前,请确保它具有-Dfile.encoding = UTF-8参数。

还请确保已将接收文件的应用程序/服务配置为接受UTF-8字符集。

如果在JVM上添加file.encoding参数没有帮助解决问题,请随时检查其他可能的相关答案,

  • 如何使UTF-8在Java Webapps中工作?
  • Spring MVC UTF-8
    编码方式