如何使用React和Node.js将input type=file上传的图片存入SQL数据库
问题核心原因与解决方案
你遇到的SQL语法报错是因为后端拿到的图片参数为空,导致SQL语句拼接后第四个参数位置没有值、多出逗号触发语法错误,根本原因是前后端的FormData传输和解析逻辑不符合规范,具体修改步骤如下:
一、前端React代码修改
- 所有请求参数都要塞进同一个FormData实例,不能把FormData当成JSON的一个属性传输
- 必须配置Axios请求头为
multipart/form-data,否则后端无法识别格式 - 阻止a标签的默认跳转行为,避免页面刷新导致请求中断
修改后的核心代码:
const addMyRestaurantToDatabase = (e) => { // 阻止a标签默认跳转 e.preventDefault() const formData = new FormData() // 所有参数都存入同一个FormData实例 formData.append('name', name) formData.append('address', address) formData.append('description', description) formData.append('myFile', image, image.name); Axios.post("http://localhost:3001/ajouter-mon-restaurant", formData, { // 必须配置该请求头 headers: { 'Content-Type': 'multipart/form-data' } }).then((response) => { console.log(response) }); };
同步修改a标签的点击事件传参:
<a href="#" onClick={(e) => addMyRestaurantToDatabase(e)}>
二、后端Node.js代码修改
默认的express.json()和express.urlencoded()中间件无法解析multipart/form-data类型的请求,需要安装multer中间件处理文件上传:
- 先安装依赖:
npm install multer - 配置multer并修改路由逻辑
如果需要直接把图片二进制存入数据库,修改后的代码如下:
const multer = require('multer') // 配置内存存储,直接读取文件的二进制buffer const storage = multer.memoryStorage() const upload = multer({ storage: storage }) // 用upload.single处理单文件上传,参数对应前端FormData里的文件字段名myFile app.post("/ajouter-mon-restaurant", upload.single('myFile'), (req, res) => { const name = req.body.name; const address = req.body.address; const description = req.body.description; // 上传的文件数据从req.file中获取 const imageBuffer = req.file.buffer; db.query( "INSERT INTO restaurant (nom, adresse, description, image_resto) VALUES (?,?,?,?)", [name, address, description, imageBuffer], (err, result) => { console.log(err); res.send('上传成功') } ); });
三、数据库字段优化
你当前使用的VARBINARY(255)最多只能存255字节的内容,连最小的缩略图都无法存储,需要修改字段类型:
- 小于64KB的小图片用
BLOB类型 - 普通大小的图片用
MEDIUMBLOB类型(最大支持16MB)
更推荐的落地方案
不建议把图片直接存入数据库,会大幅提升数据库压力、降低查询效率,更合理的做法是把图片存到服务器的静态资源目录,数据库仅存储图片的访问路径,只需修改multer的配置即可实现:
// multer磁盘存储配置 const storage = multer.diskStorage({ destination: function (req, file, cb) { // 提前在项目根目录创建public/uploads文件夹 cb(null, 'public/uploads/') }, filename: function (req, file, cb) { // 重命名文件避免重名覆盖 const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9) cb(null, uniqueSuffix + '-' + file.originalname) } }) const upload = multer({ storage: storage }) // 路由逻辑修改为存储图片路径到数据库 app.post("/ajouter-mon-restaurant", upload.single('myFile'), (req, res) => { const name = req.body.name; const address = req.body.address; const description = req.body.description; // 存储图片的访问路径 const imagePath = `/uploads/${req.file.filename}`; db.query( "INSERT INTO restaurant (nom, adresse, description, image_resto) VALUES (?,?,?,?)", [name, address, description, imagePath], (err, result) => { console.log(err); res.send('上传成功') } ); });
内容的提问来源于stack exchange,提问作者branlito
相关产品推荐
相关产品推荐

