0

I'm using Spring RestTemplate to perform POST request sending a PDF file. The filename contains some UTF-8 characters (e.g. é, è, à, ê, ë).

The problem is that after sending the request, on the other side where the request is received, the filename doesn't have the expected UTF-8 characters, and I have something like ?popi?.pdf instead.

I've tried to explicitly set UTF-8 charset in RestTemplate, but it still doesn't work.

Here is my code,

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);

}
magic_banana
  • 29
  • 2
  • 7

2 Answers2

2

according to rfc7578 when you POST a file with multipart/form-data you should use "percent-encoding" instead of filename*

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

it could be easyly realesed:

        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;
                }
            }
        });
0

Most likely the file encoding's system property of the used JVM hasn't been explicitly set, meanwhile the operating system where JVM runs is not using UTF-8 as the default charset. For instance, if JVM runs on Windows, and we don't specify the charset, the default value will be Windows-1252 instead.

Could you double check the JVM arguments of both applications that send and receive the file? Please ensure that it has -Dfile.encoding=UTF-8 argument before specifying the main class name.

Please also ensure that the application/service which receives the file has been configured to accept UTF-8 charset.

Feel free to also check the other possible related answers, if adding the file.encoding argument on JVMs doesn't help solving the problem,