如何不使用Axios实现React.js向Spring Boot REST API上传图片
React 使用 Fetch 上传文件到 Spring Boot API
首先修正你 React 代码里的关键问题,然后实现符合要求的文件上传逻辑:
1. 修正文件输入的状态保存
当前你的文件输入 onChange 事件保存的是文件路径字符串,我们需要获取实际的文件对象。修改为:
onChange={(e) => setImgOne(e.target.files[0])}
2. 实现上传函数
参照你之前的 fetch 调用写法,创建上传处理函数。注意文件上传必须使用 FormData 封装数据,且无需手动设置 Content-Type 头部(浏览器会自动添加正确的 multipart/form-data 及边界信息)。
修改后的完整 React 代码
import React, { useState } from 'react'; import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import Form from 'react-bootstrap/Form'; import Button from 'react-bootstrap/Button'; import Postview from '../componant/postview'; import Navigation from '../componant/navigation'; import Card from 'react-bootstrap/Card'; import '../pages/profile.css'; export default function Profile() { const userId = sessionStorage.getItem("userID"); const [imgOne, setImgOne] = useState(null); const [postBody, setPostBody] = useState(""); const [postTitle, setPostTitle] = useState(""); const handlePostClick = async (e) => { e.preventDefault(); if (!imgOne) { console.error("请选择要上传的图片"); return; } try { const formData = new FormData(); formData.append("File", imgOne); // 键名与 Spring Boot 接口的 @RequestParam 一致 // 可选:同时上传标题和描述 formData.append("title", postTitle); formData.append("body", postBody); const result = await fetch('http://localhost:8080/uploadFile', { method: 'POST', body: formData }); if (result.ok) { const response = await result.text(); console.log(response); // 上传成功后重置表单 setImgOne(null); setPostTitle(""); setPostBody(""); } else { console.error("上传失败"); } } catch (e) { console.error("请求出错:", e); } }; return ( <Container> <Navigation /><br /> <Row> <Col md="9"> <Postview /> </Col> <Col md="3"> <Card> <Card.Body> <Form> <Form.Group className="mb-3" controlId="imageUpload"> <Form.Label>Images</Form.Label> <Form.Control type="file" accept="image/*" onChange={(e) => setImgOne(e.target.files[0])} /> </Form.Group> <Form.Group className="mb-3" controlId="postTitle"> <Form.Label>Title</Form.Label> <Form.Control type="text" value={postTitle} onChange={(e) => setPostTitle(e.target.value)} /> </Form.Group> <Form.Group className="mb-3" controlId="postBody"> <Form.Label>Description</Form.Label> <Form.Control as="textarea" rows={3} value={postBody} onChange={(e) => setPostBody(e.target.value)} /> </Form.Group> <Button id='postBtn' variant="primary" onClick={handlePostClick} > Post </Button> </Form> </Card.Body> </Card> </Col> </Row> </Container> ); }
关键说明
- FormData 封装: 文件上传必须通过
FormData对象处理,这是浏览器支持multipart/form-data请求的标准方式。 - 参数名一致性:
formData.append("File", imgOne)中的"File"必须与 Spring Boot 接口@RequestParam("File")的参数名完全匹配,否则后端无法接收文件。 - Content-Type 自动处理: 不要手动设置
Content-Type,浏览器会自动添加包含边界标识的正确头部,手动设置会导致后端解析失败。 - 异步逻辑: 使用
async/await让请求逻辑更清晰,同时正确处理异步操作的结果与错误。
注:原代码中标题输入框使用 type="email" 疑似失误,已改为 type="text",若需邮箱类型可自行改回。
内容的提问来源于stack exchange,提问作者Dilan Tharaka
相关产品推荐
相关产品推荐

