自定义请求/响应对象中的 MultipartFile
MultipartFile inside Custom Request / Response Objects
我们可以在 Rest 模板调用的自定义请求对象中发送 MultipartFile 吗?同样,我们能否在通过 Rest 模板进行的 Rest 调用返回的自定义响应对象中接收 MutlipartFile?
基本上,我们需要在文件上传的同时发送其他基本属性,并在文件下载的同时接收一些属性。
这可以通过 Spring Rest 模板实现吗?
下面是代码,
public class UploadRequest {
private Long checkSum;
private MultiPartFile fileContents;
//setters and getters
}
我们从控制器端点接收到 MultipartFile,我们只是将它转发给
使用下面的另一个端点是 Rest 模板调用,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("uploadRequest", uploadRequest);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
它导致以下异常,
com.fasterxml.jackson.databind.exc.InvalidDefinitionException No Serializer for class java.io.FileDescriptor
和
no properties discovered to create BeanSerializer
是的,你可以。 Spring 有一个处理多部分文件的 class - org.springframework.web.multipart.MultipartFile
。您可以使用它来发送或接收多部分文件。但是请求体需要是form-data
。您不能通过 x-www-form-urlencoded
.
发送文件
只需在您的自定义请求中使用 MultipartFile
作为属性,您就可以开始了。
@Component
public class CustomRequest {
...
private Long checkSum;
private MultipartFile file;
...
// make sure you have the getters and setters right
// also the filed names are spelled exactly the same as they are in the form
// for example myFile and my_file are different
public MultiValueMap<String, String> getRequestBody() {
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("checkSum", this.getCheckSum());
requestBody.add("fileContents", this.getFileContents());
// add other fileds if you need
return requestBody;
}
}
在控制器中,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(customRequest.getRequestBody(), headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
发生的事情是您在 MultiValueMap
内发送请求正文。您必须在 MultiValueMap
内发送表单数据。并确保您的回复包含 getter 和 setter。 Spring 需要 getter setter 来序列化对象。
文档是 here
我们进行了以下更改以使其最终正常运行,
我们更改了 RestController 端点属性注释,我们有属性 UploadRequest
的 @RequestBody
注释,我们必须根据content-type-multipart-form-databoundary-charset-utf-8-not-supported 中的建议这帮助我们克服了 Http Error 415 - UnsupportedMediaType。
在客户端,我们根据Rest Api Call over Rest Template with MultipartFile
中的建议引入classFileSystemResource
public static class FileSystemResource extends ByteArrayResource {
private String fileName;
public FileSystemResource(byte[] byteArray , String filename) {
super(byteArray);
this.fileName = filename;
}
public String getFilename() { return fileName; }
public void setFilename(String fileName) { this.fileName= fileName; }
}
然后将 rest 调用更改如下,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("checkSum", request.getCheckSum());
map.add("fileContents", new FileSystemResource(request.getFile().getBytes(), request.getFile().getOriginalFileName()));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
经过这些更改后,它起作用了。
我们可以在 Rest 模板调用的自定义请求对象中发送 MultipartFile 吗?同样,我们能否在通过 Rest 模板进行的 Rest 调用返回的自定义响应对象中接收 MutlipartFile?
基本上,我们需要在文件上传的同时发送其他基本属性,并在文件下载的同时接收一些属性。
这可以通过 Spring Rest 模板实现吗?
下面是代码,
public class UploadRequest {
private Long checkSum;
private MultiPartFile fileContents;
//setters and getters
}
我们从控制器端点接收到 MultipartFile,我们只是将它转发给 使用下面的另一个端点是 Rest 模板调用,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("uploadRequest", uploadRequest);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
它导致以下异常,
com.fasterxml.jackson.databind.exc.InvalidDefinitionException No Serializer for class java.io.FileDescriptor
和
no properties discovered to create BeanSerializer
是的,你可以。 Spring 有一个处理多部分文件的 class - org.springframework.web.multipart.MultipartFile
。您可以使用它来发送或接收多部分文件。但是请求体需要是form-data
。您不能通过 x-www-form-urlencoded
.
只需在您的自定义请求中使用 MultipartFile
作为属性,您就可以开始了。
@Component
public class CustomRequest {
...
private Long checkSum;
private MultipartFile file;
...
// make sure you have the getters and setters right
// also the filed names are spelled exactly the same as they are in the form
// for example myFile and my_file are different
public MultiValueMap<String, String> getRequestBody() {
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("checkSum", this.getCheckSum());
requestBody.add("fileContents", this.getFileContents());
// add other fileds if you need
return requestBody;
}
}
在控制器中,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(customRequest.getRequestBody(), headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
发生的事情是您在 MultiValueMap
内发送请求正文。您必须在 MultiValueMap
内发送表单数据。并确保您的回复包含 getter 和 setter。 Spring 需要 getter setter 来序列化对象。
文档是 here
我们进行了以下更改以使其最终正常运行,
我们更改了 RestController 端点属性注释,我们有属性
UploadRequest
的@RequestBody
注释,我们必须根据content-type-multipart-form-databoundary-charset-utf-8-not-supported 中的建议这帮助我们克服了 Http Error 415 - UnsupportedMediaType。在客户端,我们根据Rest Api Call over Rest Template with MultipartFile
中的建议引入classFileSystemResource
public static class FileSystemResource extends ByteArrayResource {
private String fileName;
public FileSystemResource(byte[] byteArray , String filename) {
super(byteArray);
this.fileName = filename;
}
public String getFilename() { return fileName; }
public void setFilename(String fileName) { this.fileName= fileName; }
}
然后将 rest 调用更改如下,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("checkSum", request.getCheckSum());
map.add("fileContents", new FileSystemResource(request.getFile().getBytes(), request.getFile().getOriginalFileName()));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
经过这些更改后,它起作用了。