Java 如何在使用RestTemplate(从rest客户端)时为多部分上载中的文件设置内容类型

Java 如何在使用RestTemplate(从rest客户端)时为多部分上载中的文件设置内容类型,java,spring,rest,multipartform-data,resttemplate,Java,Spring,Rest,Multipartform Data,Resttemplate,我尝试上载的文件将始终是xml文件。我想将内容类型设置为application/xml 这是我的密码: MultiValueMap<String, Object parts = new LinkedMultiValueMap<String, Object(); parts.add("subject", "some info"); ByteArrayResource xmlFile = new ByteArrayResour

我尝试上载的文件将始终是xml文件。我想将内容类型设置为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'
文件的内容类型生成为“application/octet stream”,我希望它是“application/xml”
如何设置文件的内容类型?

我没有使用RestTemplate,但我以前使用过HttpClient-这是我传递正文部分的方式-

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

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

在从这个链接中得到提示后,我找到了解决方案:

解决方案是将ByteArrayResource放入具有所需标头的HttpEntity中,并将HttpEntity添加到多值映射(而不是添加ByteArrayResource本身)

代码:

Resource xmlFile=new ByteArrayResource(stringWithXMLcontent.getBytes(“UTF-8”)){
@凌驾
公共字符串getFilename(){
返回文件名;
}
};
HttpHeaders xmlHeaders=新的HttpHeaders();
setContentType(MediaType.APPLICATION_XML);
HttpEntity xmlEntity=新的HttpEntity(xmlFile,xmlHeaders);
部分。添加(“附件”,xmlEntity);

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

问题是Sprint RestTemplates使用FormHttpMessageConverter发送多部分请求。此转换器检测从资源继承的所有内容,并将其用作请求的“文件”部分。 e、 g.如果您使用多值映射,则在添加“资源”-->设置文件名、Mime类型、长度等时,您添加的每个属性都将在其自身部分中发送,。。不会成为“文件部分”的一部分

这不是答案,但它解释了为什么ByteArrayResource必须扩展以返回文件名,并作为请求的唯一部分发送。发送多个文件将使用多值映射


在Spring 4.3中,这种行为似乎已被

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

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

看看这个:或者也救了我一天!又节省了一天(至少一半:)这也是一个很好的解决方案!请允许我指出getFilename()方法是必不可少的。我最初没有覆盖它,我的目标服务根本不会将多部分识别为多部分文件,这让我发疯(我遇到了这个问题:)。通过简单地添加getFileName()方法,目标服务神奇地工作了。
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);
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();
}
@Controller
@RequestMapping("upload")
public class FileUploadController {

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

}