将获取的数据传入POST表单时遇400错误,如何解决?
问题分析与解决方案
核心问题
后端控制器依赖multer处理文件上传(multipart/form-data格式),但前端发送的是JSON格式的图片URL数组,没有实际上传文件,导致multer触发No files uploaded的校验错误,返回400状态码。
方案一:复用已有图片URL(无需上传新文件)
如果需求是直接使用从其他API获取的图片URL,不需要上传新文件,修改后端代码移除文件上传逻辑即可:
// backend/controllers/hire.js const Vehicle = require("../models/Hire"); const { StatusCodes } = require("http-status-codes"); const { BadRequestError } = require("../errors"); const AddHire = async (req, res) => { console.log("backend", req.body); // 校验必要字段(根据数据模型调整) const requiredFields = ['name', 'pictures', 'description', 'colour', 'transmission', 'type', 'seat', 'price']; const missingFields = requiredFields.filter(field => !req.body[field]); if (missingFields.length > 0) { return res.status(StatusCodes.BAD_REQUEST) .json({ error: `缺少必要字段:${missingFields.join(', ')}` }); } // 注入创建者ID req.body.createdBy = req.user.userId; // 直接使用前端传入的图片URL数组,无需Cloudinary上传 const { note, ...vehicleDetails } = req.body; const vehicleWithNote = { ...vehicleDetails, note }; const vehicle = await Vehicle.create(vehicleWithNote); res.status(StatusCodes.CREATED).json({ vehicle }); }; module.exports = { AddHire, };
方案二:上传新图片文件(适配后端multer逻辑)
如果需要用户上传新图片,前端需要改用FormData发送请求,匹配后端的文件上传逻辑:
前端Form组件修改
"use client"; import { useState } from "react"; import sendFormWithVehicleDetails from "@/lib/postHire"; export default function Form({ vehicle }: { vehicle: Vehicle }) { const { name, seat, price, description, type, colour, transmission } = vehicle; const [note, setNote] = useState(""); const [pictures, setPictures] = useState<File[]>([]); async function handleSubmit(e: React.FormEvent<HTMLFormElement>) { e.preventDefault(); const formData = new FormData(); // 添加文本字段 formData.append('name', name); formData.append('seat', seat.toString()); formData.append('price', price.toString()); formData.append('description', description); formData.append('type', type); formData.append('colour', colour); formData.append('transmission', transmission); formData.append('note', note); // 添加图片文件 pictures.forEach(file => formData.append('pictures', file)); try { await sendFormWithVehicleDetails(formData); console.log("表单提交成功"); } catch (error) { console.error("提交失败:", error); } } return ( <form onSubmit={handleSubmit}> <div className="mb-3"> <label htmlFor="examplenote1" className="form-label"> 添加备注 </label> <input type="text" className="form-control" id="exampleInputEmail1" aria-describedby="textHelp" placeholder="例如:记得带雨伞" value={note} onChange={(e) => setNote(e.target.value)} /> </div> <div className="mb-3"> <label className="form-label">上传图片(最多5张)</label> <input type="file" className="form-control" multiple accept="image/jpeg,image/png,image/svg+xml" onChange={(e) => { if (e.target.files) setPictures(Array.from(e.target.files)); }} /> </div> <button type="submit" className="btn btn-primary">提交</button> </form> ); }
请求函数修改
import Cookies from "js-cookie"; export default async function sendFormWithVehicleDetails(formData: FormData) { const url = "http://127.0.0.1:3000/api/v1/hire"; const token = Cookies.get("token"); const response = await fetch(url, { method: "POST", headers: { authorization: `Bearer ${token}`, // 不要手动设置Content-Type,浏览器会自动添加正确的multipart/form-data边界 }, body: formData, }); if (!response.ok) { const errorResponse = await response.json(); throw new Error(`请求失败,状态码${response.status}:${JSON.stringify(errorResponse)}`); } return await response.json(); }
内容的提问来源于stack exchange,提问作者coderx
相关产品推荐
相关产品推荐

