20

I need to write an application which would be able to process binary data sent by CUrl, such as:

curl localhost:8080/data --data-binary @ZYSF15A46K1.txt

I've created a POST processing method as follows:

@RequestMapping(method = RequestMethod.POST, value = "/data")
    public void acceptData(HttpEntity<byte[]> requestEntity) throws Exception {
        process(requestEntity.getBody());
    }

However it doesn't seem to be returning raw binary data. I've tried sending a GZip file and after going through Spring it is now longer decompressible, which leads me to believe I'm either getting too much data or too little data.

How do I solve this issue and get raw binary data?

JonathanReez
  • 1,559
  • 3
  • 21
  • 37
  • Try to use `HttpServletDequest` as the input parameter of your controller and read raw data from it's `InputStream`. – Horsing Apr 28 '16 at 00:02
  • @GeminiKeith tried that as well, it's always returning an empty object for some reason. – JonathanReez Apr 28 '16 at 00:24
  • have you ever set the character encoding? You can check the `Content-Length` to make sure you get the right request. If `Content-Length` valid, you can read it from `InputStream` with specific length. If not please check your request. – Horsing Apr 28 '16 at 00:33
  • @GeminiKeith Thank you! I looked a bit more into HttpServletRequest and the issue was solved (see my answer). – JonathanReez Apr 28 '16 at 01:10

2 Answers2

17

It's as easy as declaring an InputStream in your controller method's parameters:

@RequestMapping(method = RequestMethod.POST, value = "/data")
public void acceptData(InputStream dataStream) throws Exception {
    processText(dataStream);
}

You shouldn't need to disable HiddenHttpMethodFilter, if you do it's probably that your request is wrong in some way. See https://github.com/spring-projects/spring-boot/issues/5676.

nimai
  • 2,083
  • 1
  • 18
  • 16
  • 1
    "wrong in some way" = check that `Content-Type` header is set in request and that it is not `multipart/form-data` or `application/x-www-form-url-encoded` – Foyta Sep 25 '18 at 08:32
  • 1
    what annotation shall I use to get binary data from postman to spring boot? –  Jan 07 '20 at 11:08
  • it depends on how you send it with postman. See this https://learning.getpostman.com/docs/postman/sending-api-requests/requests/#sending-body-data. If you send "raw" data, you can use the declaration above as-is. – nimai Jan 07 '20 at 14:10
8

I was able to resolve this using the following code:

@Bean
public FilterRegistrationBean registration(HiddenHttpMethodFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

@RequestMapping(method = RequestMethod.POST, value = "/data")
public void acceptData(HttpServletRequest requestEntity) throws Exception {
    byte[] processedText = IOUtils.toByteArray(requestEntity.getInputStream());
    processText(processedText);
}

Spring does pre-processing by default, which causes the HttpServletRequest to be empty by the time it reaches the RequestMapping. Adding the FilterRegistrationBean Bean solves that issue.

JonathanReez
  • 1,559
  • 3
  • 21
  • 37
  • Yes, I've forgot that. Input Stream default can only be read once. – Horsing Apr 28 '16 at 01:15
  • My hunch is that funky HiddenHttpMethodFilter disable is to turn off auto multipart filtering: https://stackoverflow.com/a/32790327/32453 – rogerdpack Feb 05 '21 at 19:08