Отправка файла через службу весеннего отдыха с помощью 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 ответа
Я понял. В этой головоломке есть две части. Без изменений в сервисном коде.
Предоставление правильного конвертера для повторного шаблона. В список конвертируемых по умолчанию пружин не добавляется FormHttpMessageConverter.
FormHttpMessageConverter converter = new FormHttpMessageConverter(); RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(converter);
переопределяющий класс 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/