如何使用具有 Spring 启动后端的 React JS、Axios post 多个对象?
How to post more than one object using React JS, Axios with a Spring boot backend?
API在用Postman测试时可以工作,但是,我不知道如何从React JS的前端发送多个post请求。
我必须发送要上传的图像文件以及 int 变量 'root'.
Postman- Post 要求:-
这是SpringBoot上的API
@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;
}
这是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();
这是 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);
这是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]
请建议如何 post 请求图像文件和 'root'。
请将您的上传文件功能更改为具有多部分 header 并添加图像,root 作为 formData 的一部分,如下所示。 (更新了成本服务文件)。如果以下解决方案有效,请告诉我
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();
API在用Postman测试时可以工作,但是,我不知道如何从React JS的前端发送多个post请求。 我必须发送要上传的图像文件以及 int 变量 'root'.
Postman- Post 要求:-
这是SpringBoot上的API
@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;
}
这是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();
这是 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);
这是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]
请建议如何 post 请求图像文件和 'root'。
请将您的上传文件功能更改为具有多部分 header 并添加图像,root 作为 formData 的一部分,如下所示。 (更新了成本服务文件)。如果以下解决方案有效,请告诉我
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();