-
Notifications
You must be signed in to change notification settings - Fork 38.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resttemplate multipart post with InputStreamResource not working [SPR-13571] #18147
Comments
Brian Clozel commented In order to properly write the multipart request, the In your case, you could do the following: @RequestMapping(method = RequestMethod.POST)
public void uploadFile(@RequestParam("customerId") int customerId, @RequestPart("file") MultipartFile multipartFile) {
MultiValueMap<String,Object> parts = new LinkedMultiValueMap<>();
parts.add("customerId", customerId);
try {
parts.add("file", new MultipartFileResource(multipartFile.getInputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String,Object>> request = new HttpEntity<>(parts, headers);
restTemplate.exchange("http://localhost:8080", HttpMethod.POST, request, Void.class);
}
private class MultipartFileResource extends InputStreamResource {
public MultipartFileResource(InputStream inputStream, String filename) {
super(inputStream);
this.filename = filename;
}
@Override
public String getFilename() {
return this.filename;
}
} There are a few ways to improve this situation in the framework.
Could you try the workaround I told you about and confirm this works? Thanks! |
Greg Adams commented I've tried with code nearly identical to your comment
the restTemplate.exchange call throws the following exception:
|
Greg Adams commented It looks like the InputStreamResource.getInputStream() method is called twice, once from MultipartFileResource.contentLength() (via ResourceHttpMessageConverter.getContentLength(Resource, MediaType)) and again from ResourceHttpMessageConverter.writeInternal(Resource, HttpOutputMessage), and InputStreamResource doesn't allow multiple calls to getInputStream. |
Greg Adams commented Using something like this works:
I'm still not sure it's a good idea to call multipartFile.getBytes() like this. Doesn't that read the entire file into heap? Wouldn't that expose you to the possibility of OOM for very large files? |
Marcus Schulte commented Actually
This gives anyone inheriting from For me, a combination of a custom-named resource and a slightly altered version of
Then, a resource like the following works
Of course, the broken Converter needs to be replaced in the RestTemplate:
A method like |
Juergen Hoeller commented At this point, a dedicated So effectively, all that our check there does is to bypass a standard implementation that is known to be broken for that particular purpose: If we receive a plain That said, for any custom subclass of Juergen |
Greg Adams opened SPR-13571 and commented
I've been trying to send a multipart post via restTemplate and have been unable to get it to work with anything but FileSystemResource. In my use case (a weird file-forwarding use case) this forces me to copy a MultiPartFile InputStream into a temp file in order be able to create a FileSystemResource, which seems undesirable.
Here's a testing version of the file-receiving controller (from another project, running in another servlet container):
Here's the file-forwarding controller:
In this form, the restTemplate.exchange call throws
The ByteArrayResource form does the same thing. Only the FileSystemResource form works.
Affects: 4.1.7
Issue Links:
Referenced from: commits 27c1280
0 votes, 6 watchers
The text was updated successfully, but these errors were encountered: