如何在使用RestTemplate(来自其他客户端)时为分段上传中的文件设置内容类型

时间:2015-02-06 19:17:37

标签: java spring rest multipartform-data resttemplate

我尝试上传的文件始终是xml文件。我想将content-type设置为application / xml     这是我的代码:

         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'

原始请求如下所示:

    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 ..

正在生成文件的内容类型为&#39; application / octet-stream&#39;我希望它在哪里&#39; application / xml&#39; 如何设置文件的内容类型?

4 个答案:

答案 0 :(得分:30)

我从这个链接中提示后找出了解决方案:

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

解决方法是将ByteArrayResource放在带有必需标头的HttpEntity中,并将HttpEntity添加到Multivaluemap(而不是添加ByteArrayResource本身。)

代码:

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

答案 1 :(得分:0)

我没有使用RestTemplate,但我过去使用过HttpClient - 这就是我传递身体部位的方法 -

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

您必须查看RestTemplate中的API,它可以采用内容类型

答案 2 :(得分:0)

由于我无法评论@RGR的答案,因此我将其发布为新答案,尽管RGR的答案绝对正确。

问题是Sprint RestTemplates使用FormHttpMessageConverter发送多部分请求。此转换器检测从资源继承的所有内容,并将其用作请求的“文件”部分。 例如如果您使用MultiValueMap,则添加的每个属性都会在添加“资源”后立即发送给它自己的部分。->设置文件名,Mime-Type,长度,..将不属于“文件”部分”。

不是答案,但这是为什么必须扩展ByteArrayResource以返回文件名并作为请求的唯一部分发送的原因。发送多个文件将与MultiValueMap一起使用

SPR-13571

似乎在Spring 4.3中解决了此问题

答案 3 :(得分:0)

这是我处理文件上传和接收上传文件的方式:

public String uploadFile(byte[] fileContent, String contentType, String filename) {
    String url = "https://localhost:8000/upload";
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
    ContentDisposition contentDisposition = ContentDisposition.builder("form-data")
        .name("file")
        .filename(filename)
        .build();
    fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
    fileMap.add(HttpHeaders.CONTENT_TYPE, contentType);
    HttpEntity<byte[]> entity = new HttpEntity<>(fileContent, fileMap);
    MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    body.add("file", entity);
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
    ResponseEntity<String> response = template.exchange(url, HttpMethod.POST, requestEntity, String.class);
    return response.getBody();
}

我通过在端口8000上监听的服务来消耗它:

@Controller
@RequestMapping("upload")
public class FileUploadController {

    @PostMapping("")
    public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
        handleUploadedFile(
            file.getSize(), 
            file.getBytes(), 
            file.getContentType(), 
            file.getOriginalFilename()
        );
    }

}