Spring API request giving "Content type 'application/octet-stream' not supported" error, however request is successful when using Postman

mtibo picture mtibo · Jul 21, 2020 · Viewed 9.1k times · Source

I am trying to send an API request through my React frontend to Spring backend. When I send the request I get this error:

Could not resolve parameter [0] in private org.springframework.http.ResponseEntity com.example.bottlecap.controllers.BottlecapController.entryForm(com.example.bottlecap.domian.Bottlecap,org.springframework.web.multipart.MultipartFile): Content type 'application/octet-stream' not supported

However, when I set up the request using Postman it goes through fine. I presume there may be an issue with how I am setting up my FormData on the React end. However, I have had little luck figuring it out.

My API is supposed to recieve an object that holds data about my submission as well as an image that goes with the submission. In my Postman request, I am creating a form data that holds a JSON file that holds all the object data and a random image just for testing. As I said, the requets goes through fine with this. However, in the frontend code, I am parsing through the object data as Json and adding it to a FormData as well as adding the image to the FormData.

Here is my Spring Controller:

@RequestMapping(path ="/bottlecap/entry", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_OCTET_STREAM_VALUE})
    private ResponseEntity entryForm(@RequestPart("cap") Bottlecap cap, @RequestPart("file") MultipartFile image){
        System.out.println(cap);
        cap.toString();
        System.out.println("Test");
        return ResponseEntity.ok().build();

    }

Here is my react Frontend form submission handler:

handleSubmit = event =>{

        console.log(this.state.page);
        
        console.log(this.state.page);
        event.preventDefault();
        const cap ={
            "name":this.state.name,
            "brand":this.state.brand,
            "yearMade":parseInt(this.state.yearMade),
            "country": this.state.country,
            "description":this.state.description,
            "yearFound":parseInt(this.state.yearFound),
            "isAlcoholic":"true"
        };
        const stringCap = JSON.stringify({cap});
        console.log(cap);
        var formData = new FormData();
        formData.append('cap', JSON.parse(stringCap));
        formData.append('file',this.state.imageFile)
        
        
            axios.post('http://localhost:8080/bottlecap/entry', formData, {headers:{'Content-Type':'multipart/form-data'}})
            .then(res=>{
                console.log(res);
                console.log(res.data);
                //window.location = "/success"
                this.setState({pageDone:true})
                this.setState({pageLoading:true})
            })

    }

Here is a screenshot of my Postman request if it may help.

Also here is the contents of the json file I am sending through on Postman, if it may help as well.

{"name":"post-test",
"brand":"post-test",
"yearMade":1000,
"country":"post-test",
"description":"post-test",
"yearFound":1000,
"isAlcoholic":"true"}

The last change I did was adding a header to the axios API request, but still no luck.

Answer

Drunken Daddy picture Drunken Daddy · Jul 21, 2020

In postman, for parameter named cap, you're sending a .json file. But in your reactjs code, you're doing

formData.append('cap', JSON.parse(stringCap));

JSON.parse will create a javascript object which is not what your backend is expecting. You need to send it as a JSON file.

Not tested, but this might give you the idea.

const json = JSON.stringify(cap);
const blob = new Blob([json], {
  type: 'application/json'
});

var formData = new FormData();
formData.append('cap', blob);
formData.append('file', this.state.imageFile)

axios.post('http://localhost:8080/bottlecap/entry', formData, {headers:{'Content-Type':'multipart/form-data'}})
        .then(res=>{
    console.log(res.data);
}