Отправка файла через службу весеннего отдыха с помощью resttemplate

Название может показаться обычным, но ни один из них не вписывается в мою проблему

У меня есть служба отдыха, которая принимает обычные параметры и файл в виде multipart.

Я хочу использовать resttemplate для отправки данных и файлов в службу покоя выше.

до того времени, как я отправлял обычные строковые данные, проблем не было. как только я добавляю код отправки байтов, я начинаю получать ошибку 400 Bad request.

если я комментирую код для отправки 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 ответа

Я понял. В этой головоломке есть две части. Без изменений в сервисном коде.

  1. Предоставление правильного конвертера для повторного шаблона. В список конвертируемых по умолчанию пружин не добавляется 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;
           }
    
       }
    

После вышеуказанных изменений код клиента будет

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

Первый, value="/createTicket.do" это далеко от REST конвенции. То же самое касается /ticket, Создание заявки должно быть сделано POST на URL: .../tickets/

Другие вопросы по тегам