You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:53:12