简体   繁体   中英

How to set content-type for the file in multipart upload when using RestTemplate (from a rest client)

The file i'm trying to upload will always be a xml file. I want to set the content-type as application/xml Here is my code:

         MultiValueMap<String, Object parts = new LinkedMultiValueMap<String,
         Object(); parts.add("subject", "some info"); 
         ByteArrayResource xmlFile = new    ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
                 @Override
                 public String getFilename(){
                     return documentName;
                 }             
             };

     parts.add("attachment", xmlFile);

//sending the request using RestTemplate template;, the request is successfull 
String result = template.postForObject(getRestURI(), httpEntity,String.class);      
//but the content-type of file is 'application/octet-stream'

the raw request looks like this:

    Content-Type:
    multipart/form-data;boundary=gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz
    User-Agent: Java/1.7.0_67 Host: some.host Connection: keep-alive
    Content-Length: 202866

    --gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data;    name="subject" Content-Type: text/plain;charset=ISO-8859-1
    Content-Length: 19

    some info

    --gbTw7ZJbcdbHIeCRqdX81DVTFfA-oteHHEqgmlz Content-Disposition: form-data;   name="attachment"; filename="filename.xml" Content-Type:
    application/octet-stream Content-Length: 201402

    ....xml file contents here ..

The content-type of the file is being generated as 'application/octet-stream' where as i want it to be 'application/xml' How can i set the content type for the file?

I figured out the solution after taking hint from this link:

Making a multipart post request with compressed jpeg byte array with spring for android

Solution is to put the ByteArrayResource in a HttpEntity with required header and add the HttpEntity to Multivaluemap (Instead of adding ByteArrayResource itself.)

Code:

Resource xmlFile = new ByteArrayResource(stringWithXMLcontent.getBytes("UTF-8")){
            @Override
            public String getFilename(){
                return documentName;
            }
        };
        HttpHeaders xmlHeaders = new HttpHeaders();
        xmlHeaders.setContentType(MediaType.APPLICATION_XML);
        HttpEntity<Resource> xmlEntity = new HttpEntity<Resource>(xmlFile, xmlHeaders);
        parts.add("attachment", xmlEntity);

I've not used RestTemplate but i've used HttpClient in past - This is how i pass the body part -

MultipartEntityBuilder eb = MultipartEntityBuilder.create().setBoundary(MULTIPART_BOUNDARY)
                .addTextBody(BODYPART_ENTITY, key, ContentType.create("application/xml", Charset.forName("UTF-8")));

You will have to look at for API in RestTemplate which can take content-type

As i can not comment the answer of @RGR I'm posting this as new answer although RGR's answer is absolutely correct.

The problem is, that the Sprint RestTemplates uses FormHttpMessageConverter to send the multi part request. This converter detects everything that inherits from Resource and uses this as the request's "file" part. eg If you use a MultiValueMap every property you add will be send in it's own part as soon as you add a "Resource"...--> Setting filename, Mime-Type, length,.. will not be part of the "file part".

Not an answer, but it's the explanation why ByteArrayResource must be extended to return the filename and be send as the only part of the request. Sending multiple files will work with a MultiValueMap

It looks like this behaviour was fixed in Spring 4.3 by SPR-13571

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM