如何使用 spring RestTemplate 发送 multipartFile?
How do I send a multipartFile using spring RestTemplate?
我正在尝试 POST 从一个 SpringBoot 应用程序到另一个 SpringBoot 应用程序的文件。
我试图达到的点看起来像
@PostMapping(
value = "/upload",
consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ArmResponse<JobData>> uploadInvoices(@RequestParam("file") MultipartFile interestingStuff) {
String incomingFilename = interestingStuff.getName();
String originalFilename = interestingStuff.getOriginalFilename();
String contentType = interestingStuff.getContentType();
// do interesting stuff here
return ok(successfulResponse(new JobData()));
}
应用中的代码向 thios 端点执行 POST 请求类似于
public void loadInvoices(MultipartFile invoices) throws IOException {
File invoicesFile = new File(invoices.getOriginalFilename());
invoices.transferTo(invoicesFile);
LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("file", invoicesFile);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);
final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter<Source>());
RestTemplate template = new RestTemplate(messageConverters);
template.exchange(
url,
HttpMethod.POST,
httpEntity,
new ParameterizedTypeReference<ArmResponse<JobData>>() {
});
}
如果我 post 使用 postman 形式的文件 - 它有效
Postman 请求中的 content-type header 看起来像
content-type:"multipart/form-data; boundary=--------------------------286899320410555838190774"
当 POST 由 RestTemplate 执行时,出现以下错误。
com.fasterxml.jackson.databind.exc.MismatchedInputException:由于end-of-input at [Source: (String)"",没有要映射的内容;行:1,列:0]
我怀疑请求中发送的 content-type header 是错误的。
有谁知道如何为 MULTIPART_FORM_DATA 正确设置 content-type header?
为什么需要消息转换器?只需使用本教程中的代码即可:https://www.baeldung.com/spring-rest-template-multipart-upload
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity(url , httpEntity, String.class);
解决方案和往常一样非常简单。只需在 multipartFile 上调用 getResource()。
public void loadInvoices(MultipartFile invoices) throws IOException {
Resource invoicesResource = invoices.getResource();
LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("file", invoicesResource);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
restTemplate.postForEntity("my/url", httpEntity, SommeClass.class);
}
Kotlin 中稍微漂亮一点的解决方案:
@Test
fun testMultipartUpload() {
val bytes = ByteArray(10240) // Get your bytes however you like.
val resource = object : ByteArrayResource(bytes) {
override fun getFilename() = "xyzzy.jpg"
}
val request = RequestEntity.post("/foobar")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(LinkedMultiValueMap<String, Any>().apply { add("data", resource) })
val result = testRestTemplate.exchange(request, FooBar::class.java)
Assertions.assertTrue(result.statusCode.is2xxSuccessful)
}
我正在尝试 POST 从一个 SpringBoot 应用程序到另一个 SpringBoot 应用程序的文件。 我试图达到的点看起来像
@PostMapping(
value = "/upload",
consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ArmResponse<JobData>> uploadInvoices(@RequestParam("file") MultipartFile interestingStuff) {
String incomingFilename = interestingStuff.getName();
String originalFilename = interestingStuff.getOriginalFilename();
String contentType = interestingStuff.getContentType();
// do interesting stuff here
return ok(successfulResponse(new JobData()));
}
应用中的代码向 thios 端点执行 POST 请求类似于
public void loadInvoices(MultipartFile invoices) throws IOException {
File invoicesFile = new File(invoices.getOriginalFilename());
invoices.transferTo(invoicesFile);
LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("file", invoicesFile);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);
final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter<Source>());
RestTemplate template = new RestTemplate(messageConverters);
template.exchange(
url,
HttpMethod.POST,
httpEntity,
new ParameterizedTypeReference<ArmResponse<JobData>>() {
});
}
如果我 post 使用 postman 形式的文件 - 它有效 Postman 请求中的 content-type header 看起来像
content-type:"multipart/form-data; boundary=--------------------------286899320410555838190774"
当 POST 由 RestTemplate 执行时,出现以下错误。
com.fasterxml.jackson.databind.exc.MismatchedInputException:由于end-of-input at [Source: (String)"",没有要映射的内容;行:1,列:0]
我怀疑请求中发送的 content-type header 是错误的。 有谁知道如何为 MULTIPART_FORM_DATA 正确设置 content-type header?
为什么需要消息转换器?只需使用本教程中的代码即可:https://www.baeldung.com/spring-rest-template-multipart-upload
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity(url , httpEntity, String.class);
解决方案和往常一样非常简单。只需在 multipartFile 上调用 getResource()。
public void loadInvoices(MultipartFile invoices) throws IOException {
Resource invoicesResource = invoices.getResource();
LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("file", invoicesResource);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
restTemplate.postForEntity("my/url", httpEntity, SommeClass.class);
}
Kotlin 中稍微漂亮一点的解决方案:
@Test
fun testMultipartUpload() {
val bytes = ByteArray(10240) // Get your bytes however you like.
val resource = object : ByteArrayResource(bytes) {
override fun getFilename() = "xyzzy.jpg"
}
val request = RequestEntity.post("/foobar")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(LinkedMultiValueMap<String, Any>().apply { add("data", resource) })
val result = testRestTemplate.exchange(request, FooBar::class.java)
Assertions.assertTrue(result.statusCode.is2xxSuccessful)
}