通过Form Data上传截图时遇'Cannot POST'错误,如何解决?
解决React+Express上传截图时的Cannot POST错误及文件上传问题
一、先解决「Cannot POST」错误
原代码中表单存在默认提交行为:点击按钮时,浏览器会自动触发表单自带的POST请求(因form标签设置了method="POST"),而非执行你写的axios请求,导致路由不匹配出现错误。
修复后的前端代码
import React, { useState } from "react"; import axios from "axios"; const App = () => { const [name, setName] = useState(''); const [screenshot, setScreenshot] = useState(null); // 阻止表单默认提交行为,执行自定义上传逻辑 const handleSubmit = async (e) => { e.preventDefault(); if (!screenshot) { console.log('请选择截图文件'); return; } // 构建FormData对象,用于承载文本数据和文件 const formData = new FormData(); formData.append('name', name); formData.append('screenshot', screenshot); try { const response = await axios.post('/api/data', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); console.log(response.data); } catch (error) { console.log('Error: ', error); } }; return ( <div> <form onSubmit={handleSubmit}> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="输入名称" /><br /> <input type="file" accept="image/png, image/jpeg" onChange={(e) => setScreenshot(e.target.files[0])} /><br /> <button type="submit">Submit</button> </form> </div> ); }; export default App;
二、后端适配文件上传
原后端使用bodyParser.json()无法处理multipart/form-data类型的请求(文件上传必须用该类型),需要引入multer中间件处理文件上传逻辑。
步骤1:安装multer
npm install multer
修复后的后端代码
const express = require('express'); const mysql = require('mysql'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const app = express(); const port = 3001; // 配置multer:设置文件存储路径和唯一文件名 const storage = multer.diskStorage({ destination: function (req, file, cb) { const uploadDir = path.join(__dirname, 'uploads'); // 自动创建uploads文件夹(如果不存在) if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir); } cb(null, uploadDir); }, filename: function (req, file, cb) { // 生成唯一文件名,避免文件覆盖 const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, `${file.fieldname}-${uniqueSuffix}${path.extname(file.originalname)}`); } }); const upload = multer({ storage: storage }); // 数据库连接配置 var connection = mysql.createConnection({ host: 'localhost', user: 'root', password: '', // 填写你的MySQL密码 database: 'mydb' }); connection.connect(); // 处理文件上传+数据插入:upload.single('screenshot')对应前端的文件字段名 app.post('/api/data', upload.single('screenshot'), (req, res) => { const { name } = req.body; const screenshotPath = req.file ? `/uploads/${req.file.filename}` : null; if (!name || !screenshotPath) { return res.status(400).json({ err: '名称和截图不能为空' }); } // 插入数据到数据库(需确保表包含对应字段) const sql = 'INSERT INTO mytable(Name, ScreenshotPath) VALUES(?, ?)'; connection.query(sql, [name, screenshotPath], (err, result) => { if (err) { console.log("插入数据错误", err); return res.status(500).json({ err: '插入数据失败' }); } console.log('数据插入成功: ', result); res.json({ message: '数据和截图上传成功' }); }); }); // 静态托管uploads文件夹,允许前端直接访问上传的图片 app.use('/uploads', express.static(path.join(__dirname, 'uploads'))); app.listen(port, () => console.log(`服务器运行在端口 ${port}`));
三、数据库表结构调整
确保你的mytable表包含存储文件路径的字段,执行以下SQL创建或修改表:
CREATE TABLE mytable ( id INT AUTO_INCREMENT PRIMARY KEY, Name VARCHAR(255) NOT NULL, ScreenshotPath VARCHAR(255) NOT NULL );
核心问题总结
- 「Cannot POST」错误:表单默认提交行为未阻止,浏览器发起了未匹配后端路由的默认请求,通过
e.preventDefault()解决。 - 文件上传失败:原代码未处理文件字段、未使用FormData承载文件,后端未配置multer处理
multipart/form-data请求。 - 数据库存储逻辑:文件实际存储在服务器本地,数据库仅保存文件路径,便于后续访问和管理。
内容的提问来源于stack exchange,提问作者Ritik Notiyal
相关产品推荐
相关产品推荐

