通过resttemplate在spring rest服务上发送文件

时间:2017-08-02 21:55:28

标签: java spring rest spring-mvc resttemplate

标题可能看起来很常见,但它们都不适合我的问题。

我有一个休息服务,它接受普通参数和多部分形式的文件。

我想使用resttemplate将数据和文件发送到上述休息服务。

直到我发送正常的字符串数据时没有问题。一旦我添加了发送字节的代码,我就开始收到 400 Bad request error。

如果我评论代码发送ByteArrayResource,那么它就开始正常参数。

下面是示例代码

休息服务控制器

@RestController
@RequestMapping(value="/ticket")
public class UserTicketController {

 @RequestMapping(value="/createTicket.do",method={RequestMethod.POST},
        consumes = {MediaType.MULTIPART_FORM_DATA_VALUE},headers={"content-type="+MediaType.MULTIPART_FORM_DATA_VALUE})
public void createTicket(@ModelAttribute ServiceDeskRequest serviceDeskRequest, HttpServletRequest request,HttpServletResponse response) throws Exception{

 }

 }

Servicedeskrequest模型属性是

 public class ServiceDeskRequest implements Serializable{


private String jsonData;
private MultipartFile attachment;
}

应用context.xml中

 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean> 

客户端代码

RestTemplate restTemplate = new RestTemplate();
        MultiValueMap<String, Object> requestParamerterMap = new LinkedMultiValueMap<String, Object>();

        requestParamerterMap.add("jsonData", jsonData);
        MultipartFile attachment = userRequest.getAttachment();

        if(attachment!=null && attachment.getOriginalFilename()!=null) {
            ByteArrayResource byteArrayResource = new ByteArrayResource(attachment.getBytes(), attachment.getOriginalFilename());
            requestParamerterMap.add("attachment", byteArrayResource);
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(requestParamerterMap, headers);


        String response = restTemplate.postForObject(targetUrl, requestEntity, String.class);

2 个答案:

答案 0 :(得分:1)

我明白了。这个难题有两个部分。服务代码没有变化。

  1. 提供正确的转换器来重新模板。在默认转换列表中,spring不会添加FormHttpMessageConverter。

        FormHttpMessageConverter converter = new FormHttpMessageConverter();
    
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(converter);
    
  2. 覆盖bytearrayresource类。请注意,您需要覆盖 getFilename 方法,以便在服务端接收文档名称。

         public class MultipartByteArrayResource extends ByteArrayResource{
    
         private String fileName;
    
          public MultipartByteArrayResource(byte[] byteArray) {
                 super(byteArray);
             }
    
          public String getFilename() { 
              return fileName; 
            }
    
          public void setFilename(String fileName) {
              this.fileName= fileName;
           }
    
       }
    
  3. 经过上述更改后,客户端代码将

           FormHttpMessageConverter converter = new FormHttpMessageConverter();
    
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(converter);
    
            MultiValueMap<String, Object> requestParamerterMap = new LinkedMultiValueMap<String, Object>();
    
            requestParamerterMap.add("jsonData", jsonData);
    
            MultipartFile attachment = userRequest.getAttachment();
    
            if(attachment!=null && attachment.getOriginalFilename()!=null) {
                //ByteArrayResource byteArrayResource = new ByteArrayResource(attachment.getBytes(), attachment.getOriginalFilename());
    
                MultipartByteArrayResource resource = new MultipartByteArrayResource(attachment.getBytes());
    
               //pass file name sepratly 
               resource.setFilename(attachment.getOriginalFilename());
    
                requestParamerterMap.add("attachment", resource);
            }
    
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(requestParamerterMap, headers);
    
            String response = restTemplate.postForObject(targetUrls.get("sdCreateTicketsUrl"), requestEntity, String.class);
    

答案 1 :(得分:0)

首先,value="/createTicket.do"远离REST约定。同样适用于/ticket。 应通过POST到URL来创建故障单:.../tickets/