Issue
The API works when tested with Postman, however, I do not know how to send more than one post request from the front end of React JS. I have to send the image file to be uploaded along with the int variable 'root'.
Postman- Post Request:- href="https://i.stack.imgur.com/N8GAq.png" rel="nofollow noreferrer">
This is the API on SpringBoot
@PostMapping("/cost_image_upload")
public status uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("root") String root) throws IOException {
List<cost> costs = costRepository.findAll();
for(cost cost: costs) {
if(cost.getRoot().equals(root)) {
byte[] temp = file.getBytes();
cost.setImage(temp);
this.costRepository.save(cost);
System.out.println("worked" + cost);
return status.SUCCESS;
}
}
System.out.println("didn't work");
return status.FAILURE;
}
This is CostService.js
import axios from 'axios';
const user_base_url = "http://localhost:8080/api";
class CostService{
addCost(cost) {
return axios.post(user_base_url + '/cost', cost);
}
uploadFile(image, root) {
return axios.post(user_base_url + '/cost_image_upload', image, root);
}
showCost() {
return axios.get(user_base_url + '/costings');
}
}
export default new CostService();
This is Front end on React JS (StyleComponent.jsx)
import React, { Component } from 'react';
import {Row, Col, Card, Form, Button, Alert} from 'react-bootstrap';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {faSignInAlt} from "@fortawesome/free-solid-svg-icons";
import CostService from '../services/CostService';
// import axios from 'axios';
class StyleComponent extends Component {
constructor(props) {
super(props);
this.state = this.initialState;
this.isValid = false
this.addCost = this.addCost.bind(this);
}
initialState = {
temp:null, cID:null, root:null, priMat1:null, priMat2:null, actSize:null, image:null, firstQuote:null, firstComm:null, secQuote:null, secComm:null, vendorTarget1:null, thirdQuote:null, thirdComm:null, vendorTarget2:null, fourthQuote:null, error:null, error_success:null, selectedFile:null
};
onFileChange = event => {
// Update the state
this.setState({ selectedFile: event.target.files[0] });
};
onFileChange = event => {
// Update the state
this.setState({ selectedFile: event.target.files[0] });
};
uploadFile = (rootID) => {
};
componentDidMount() {
// call cost API
// call COST_IMAGE API
}
credentialChange = event => {
this.setState({
[event.target.name] : event.target.value
});
};
addCost = () => {
let cost = {
cID: this.state.cID,
root: this.state.root,
priMat1: this.state.priMat1,
priMat2: this.state.priMat2,
actSize: this.state.actSize,
image: this.state.image,
firstQuote: this.state.firstQuote,
firstComm: this.state.firstComm,
secQuote: this.state.secQuote,
secComm: this.state.secComm,
vendorTarget1: this.state.vendorTarget1,
thirdQuote: this.state.thirdQuote,
thirdComm: this.state.thirdComm,
vendorTarget2: this.state.vendorTarget2,
fourthQuote: this.state.fourthQuote,
};
CostService.addCost(cost).then((res) => {
console.log(res.data);
this.state.temp= res.data;
console.log(this.state.temp);
console.log(this.state.selectedFile);
CostService.uploadFile(this.state.selectedFile, res.data).then((res2) => {
if(res2.data === 'SUCCESS') {
console.log("Success");
this.setState({error_success:"The file has been uploaded!"});
} else if(res2.data === 'FAILURE') {
console.log("Failure");
this.setState({error:"The file could not be uploaded!"});
}
})
})
};
resetRegisterForm = () => {
this.setState(() => this.initialState);
};
render() {
const {error, error_success} = this.state;
return (
<div>
<br></br>
<br></br>
{error_success && <Alert variant="success">{error_success}</Alert>}
{error && <Alert variant="danger">{error}</Alert>}
<Card>
<Card.Header className={"border border-light bg-light text-black"}>
<FontAwesomeIcon icon={faSignInAlt}/> Add a New Style!
</Card.Header>
<br></br>
<Form>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridcID">
<Form.Label>Costing Tool ID</Form.Label>
<Form.Control type="text" name="cID" placeholder="Enter Costing Tool ID" onChange={this.credentialChange}/>
</Form.Group>
<Form.Group as={Col} controlId="formGridRoot">
<Form.Label>Style Number</Form.Label>
<Form.Control type="text" name="root" placeholder="Enter Style Number Root" onChange={this.credentialChange}/>
</Form.Group>
<Form.Group as={Col} controlId="formGridPriMat1">
<Form.Label>Primary Material</Form.Label>
<Form.Control type="text" name ="priMat1" placeholder="Specify Primary Material" onChange={this.credentialChange}/>
</Form.Group>
<Form.Group as={Col} controlId="formGridPriMat2">
<Form.Label>Secondary Material</Form.Label>
<Form.Control type="text" name ="priMat2" placeholder="Specify Secondary Material" onChange={this.credentialChange}/>
</Form.Group>
<Form.Group as={Col} controlId="formGridSize">
<Form.Label>Size Range</Form.Label>
<Form.Control type="text" name ="actSize" placeholder="Specify Size Range" onChange={this.credentialChange}/>
</Form.Group>
<input className= "form-control chosen-select" type="file" onChange={this.onFileChange}/><br></br>
</Row>
<div align="right">
<Button variant="outline-success" type="submit"
onClick={this.addCost}>
Register
</Button>
<Button variant="outline-primary" type="reset">
Reset
</Button>
<br></br>
<br></br>
</div>
</Form>
</Card>
</div>
);
}
}
export default (StyleComponent);
This is the warning message on Springboot
2022-03-24 23:20:17.538 WARN 24028 --- [nio-8080-exec-5] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'root' for method parameter type String is not present]
Please suggest how to post requests for both image-file and 'root'.
Solution
Please change your upload file function to have multipart header and add the image, root as part of formData like below. (Updated the cost service file). Do let me know if the below solution works
import axios from 'axios';
const user_base_url = "http://localhost:8080/api";
class CostService{
addCost(cost) {
return axios.post(user_base_url + '/cost', cost);
}
uploadFile(image, root) {
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
const formData = new FormData();
formData.append('file', image);
formData.append('root', root);
return axios.post(user_base_url + '/cost_image_upload', formData, config);
}
showCost() {
return axios.get(user_base_url + '/costings');
}
}
export default new CostService();
Answered By - Aditya Akella
Answer Checked By - David Marino (JavaFixing Volunteer)