The other day, I was trying to build a simple batch upload interface for a Java web application running Spring Boot with Spring MVC on Apache Tomcat. But when I tried reading the InputStream in my controller, it was always empty. Fortunately, this turned out to be quite easy to fix.
This is the command line I used to upload the data:
curl -X POST localhost:8080/ --data-binary @- < input.txt
And that's the Java code:
@RestController public class MyController { @PostMapping("/") public String batchUpload(InputStream in) throws IOException { // do something with the InputStream } }
Spring MVC supports InputStream and Reader for accessing the request body, but it didn't make a difference here, no matter which I used they were both empty. For larger amounts of data (more than 2 MB in my tests), the input was always complete, however.
It turns out that there's a mechanism at work that consumes at least part of the body, but only if the Content-Type header is set to application/x-www-form-urlencoded, which is the default that browsers and tools like curl use.
The workaround is trivial - just use a different Content-Typeheader, which in my case is the proper solution anyway:
curl -X POST localhost:8080/ -H "Content-Type: application/octet-stream" --data-binary @- < input.txt
I usually restrict the endpoint to only accept a custom Content-Type, so this is a problem that only shows up during prototyping.