How to get raw binary data from a POST request processed by Spring?
Asked Answered
S

2

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?

Sadfaced answered 27/4, 2016 at 22:1 Comment(4)
Try to use HttpServletDequest as the input parameter of your controller and read raw data from it's InputStream.Meagre
@GeminiKeith tried that as well, it's always returning an empty object for some reason.Sadfaced
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.Meagre
@GeminiKeith Thank you! I looked a bit more into HttpServletRequest and the issue was solved (see my answer).Sadfaced
H
19

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.

Hokusai answered 7/2, 2018 at 22:28 Comment(3)
"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-encodedYonit
what annotation shall I use to get binary data from postman to spring boot?Europe
it depends on how you send it with postman. See this learning.getpostman.com/docs/postman/sending-api-requests/…. If you send "raw" data, you can use the declaration above as-is.Hokusai
S
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.

Sadfaced answered 28/4, 2016 at 1:9 Comment(2)
Yes, I've forgot that. Input Stream default can only be read once.Meagre
My hunch is that funky HiddenHttpMethodFilter disable is to turn off auto multipart filtering: https://mcmap.net/q/361950/-springboot-large-streaming-file-upload-using-apache-commons-fileuploadTrifocal

© 2022 - 2024 — McMap. All rights reserved.