React - 上传到 Spring API 的第一个文件不起作用,再试一次,第二次尝试是否正常?
React - 1st file upload to Spring API doesn't work, try again and it works fine on second try?
你好
我开发了一个前端 React 项目,它向 SpringBoot REST API 请求资源和逻辑。我最近实现了文件上传,我使用 React 创建的表单在第一次尝试时总是失败,但是当我再次单击它并上传另一个文件时(哪个文件无关紧要,不是文件导致的),它成功上传了通过 POST 以二进制文件作为有效载荷的文件。
第一个请求的负载为 'undefined'。
反应形式:
const UPDATE_USER_URL = 'http://localhost:8080/users/update-user-details';
const UPLOAD_FILE_URL = 'http://localhost:8080/image-files';
class UpdateUserForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: localStorage.getItem("username"),
location: "",
bio: ""
};
this.onSubmit = this.onSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
onFileChangeHandler = (e) => {
e.preventDefault();
this.setState({
selectedFile: e.target.files[0]
});
const formData = new FormData();
formData.append('file', this.state.selectedFile);
const USER_UPLOAD_FILE_URL = UPLOAD_FILE_URL + "/" + this.state.username;
fetch(USER_UPLOAD_FILE_URL, {
method: 'POST',
headers: {
"Authorization": localStorage.getItem("token")
},
body: formData
}).then(res => {
if(res.ok) {
console.log(res.data);
alert("File uploaded successfully.")
}
});
};
onSubmit(event) {
event.preventDefault();
const payload = {
"username": this.state.username,
"location": this.capital_letter(this.state.location),
"bio": this.state.bio
};
fetch(UPDATE_USER_URL, {
method: 'PUT',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
body: JSON.stringify(payload)
})
.then(response => response.json())
.then((data) => {
console.log(data);
});
}
//https://www.w3resource.com/javascript-exercises/javascript-basic-exercise-50.php
capital_letter(str) {
str = str.split(" ");
for (var i = 0, x = str.length; i < x; i++) {
str[i] = str[i][0].toUpperCase() + str[i].substr(1);
}
console.log(str)
return str.join(" ");
}
generateUploadUrl(username) {
}
render() {
return (
<div className="outer-div-container">
<div>
<AppNavbar/>
<div id="form-container">
<div id="form-div">
<h5 id="form-heading">Update Details</h5>
<br />
<div className="outer-div-container">
<form onSubmit={this.onSubmit}>
<label className="form-label" id="top-form-label">
Location:
<br />
<input
className="form-input"
//Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwhen
maxLength="85"
//No min length as places with 1 letter e.g: A, S.
name="location"
type="text"
value={this.state.location}
onChange={this.handleInputChange} />
</label>
<br />
<label className="form-label">
Bio:
<br />
<input
className="form-input"
minLength="3"
name="bio"
type="text"
value={this.state.bio}
onChange={this.handleInputChange} />
</label>
<label>Upload Your File </label>
<input type="file" className="form-control" name="file" onChange={this.onFileChangeHandler}/>
<br />
<input id="form-submit" type="submit" value="Submit" />
</form>
<div className="form-group files color">
<label>Upload Your File </label>
<input type="file" className="form-control" name="file" onChange={this.onFileChangeHandler}/>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default UpdateUserForm;
控制器:
@RestController
@RequestMapping("image-files")
@AllArgsConstructor
@CrossOrigin("*")
public class ImageFileController {
ImageFileService service;
@GetMapping(value = "/{username}")
public byte[] downloadImageFile(@PathVariable String username) {
return service.downloadImageFile(username);
}
}
非常感谢任何帮助,我完全被难住了,谢谢。
在您的 onFileChangeHandler
函数中,您将文件设置为 selectedFile
状态,然后像
一样立即再次访问它
formData.append('file', this.state.selectedFile);
你不能将某些东西设置为反应状态并在下一行再次访问它,这是因为 setState
在反应中异步工作。这意味着如果你想从反应状态中获取最新的设置值,你需要等待下一次重新渲染发生。否则,您将只能从状态中获取先前设置的值,在您的情况下为 undefined
。所以在你的函数中,将文件数据直接传递给formData
。试试下面的代码
onFileChangeHandler = (e) => {
e.preventDefault();
const fileData = e.target.files[0];
this.setState({
selectedFile: fileData
});
const formData = new FormData();
formData.append('file', fileData);
const USER_UPLOAD_FILE_URL = UPLOAD_FILE_URL + "/" + this.state.username;
fetch(USER_UPLOAD_FILE_URL, {
method: 'POST',
headers: {
"Authorization": localStorage.getItem("token")
},
body: formData
}).then(res => {
if(res.ok) {
console.log(res.data);
alert("File uploaded successfully.")
}
});
};
你好
我开发了一个前端 React 项目,它向 SpringBoot REST API 请求资源和逻辑。我最近实现了文件上传,我使用 React 创建的表单在第一次尝试时总是失败,但是当我再次单击它并上传另一个文件时(哪个文件无关紧要,不是文件导致的),它成功上传了通过 POST 以二进制文件作为有效载荷的文件。
第一个请求的负载为 'undefined'。
反应形式:
const UPDATE_USER_URL = 'http://localhost:8080/users/update-user-details';
const UPLOAD_FILE_URL = 'http://localhost:8080/image-files';
class UpdateUserForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: localStorage.getItem("username"),
location: "",
bio: ""
};
this.onSubmit = this.onSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
onFileChangeHandler = (e) => {
e.preventDefault();
this.setState({
selectedFile: e.target.files[0]
});
const formData = new FormData();
formData.append('file', this.state.selectedFile);
const USER_UPLOAD_FILE_URL = UPLOAD_FILE_URL + "/" + this.state.username;
fetch(USER_UPLOAD_FILE_URL, {
method: 'POST',
headers: {
"Authorization": localStorage.getItem("token")
},
body: formData
}).then(res => {
if(res.ok) {
console.log(res.data);
alert("File uploaded successfully.")
}
});
};
onSubmit(event) {
event.preventDefault();
const payload = {
"username": this.state.username,
"location": this.capital_letter(this.state.location),
"bio": this.state.bio
};
fetch(UPDATE_USER_URL, {
method: 'PUT',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
body: JSON.stringify(payload)
})
.then(response => response.json())
.then((data) => {
console.log(data);
});
}
//https://www.w3resource.com/javascript-exercises/javascript-basic-exercise-50.php
capital_letter(str) {
str = str.split(" ");
for (var i = 0, x = str.length; i < x; i++) {
str[i] = str[i][0].toUpperCase() + str[i].substr(1);
}
console.log(str)
return str.join(" ");
}
generateUploadUrl(username) {
}
render() {
return (
<div className="outer-div-container">
<div>
<AppNavbar/>
<div id="form-container">
<div id="form-div">
<h5 id="form-heading">Update Details</h5>
<br />
<div className="outer-div-container">
<form onSubmit={this.onSubmit}>
<label className="form-label" id="top-form-label">
Location:
<br />
<input
className="form-input"
//Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwhen
maxLength="85"
//No min length as places with 1 letter e.g: A, S.
name="location"
type="text"
value={this.state.location}
onChange={this.handleInputChange} />
</label>
<br />
<label className="form-label">
Bio:
<br />
<input
className="form-input"
minLength="3"
name="bio"
type="text"
value={this.state.bio}
onChange={this.handleInputChange} />
</label>
<label>Upload Your File </label>
<input type="file" className="form-control" name="file" onChange={this.onFileChangeHandler}/>
<br />
<input id="form-submit" type="submit" value="Submit" />
</form>
<div className="form-group files color">
<label>Upload Your File </label>
<input type="file" className="form-control" name="file" onChange={this.onFileChangeHandler}/>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default UpdateUserForm;
控制器:
@RestController
@RequestMapping("image-files")
@AllArgsConstructor
@CrossOrigin("*")
public class ImageFileController {
ImageFileService service;
@GetMapping(value = "/{username}")
public byte[] downloadImageFile(@PathVariable String username) {
return service.downloadImageFile(username);
}
}
非常感谢任何帮助,我完全被难住了,谢谢。
在您的 onFileChangeHandler
函数中,您将文件设置为 selectedFile
状态,然后像
formData.append('file', this.state.selectedFile);
你不能将某些东西设置为反应状态并在下一行再次访问它,这是因为 setState
在反应中异步工作。这意味着如果你想从反应状态中获取最新的设置值,你需要等待下一次重新渲染发生。否则,您将只能从状态中获取先前设置的值,在您的情况下为 undefined
。所以在你的函数中,将文件数据直接传递给formData
。试试下面的代码
onFileChangeHandler = (e) => {
e.preventDefault();
const fileData = e.target.files[0];
this.setState({
selectedFile: fileData
});
const formData = new FormData();
formData.append('file', fileData);
const USER_UPLOAD_FILE_URL = UPLOAD_FILE_URL + "/" + this.state.username;
fetch(USER_UPLOAD_FILE_URL, {
method: 'POST',
headers: {
"Authorization": localStorage.getItem("token")
},
body: formData
}).then(res => {
if(res.ok) {
console.log(res.data);
alert("File uploaded successfully.")
}
});
};