Next.js使用formidable上传图片时出现API resolved without sending a response错误
报错根因
Register异步函数中调用handlePost时未添加await修饰,函数在整个上传、入库、响应逻辑执行完毕前就已退出,Next.js检测到API路由执行完成但未返回响应,因此抛出该告警formidable的parse方法为回调风格,未做Promise包装时外层无法捕获异步逻辑的执行状态,也会导致响应时序异常- 缺少异常捕获分支,一旦入库、文件写入逻辑报错,会出现无响应返回的情况
修复方案
你可以直接使用以下修改后的代码:
import connection from "../../../utils/connection/getConnection"; import formidable from "formidable"; const signupSchema = require("../../../models/signup"); import mkdirp from "mkdirp"; import bcrpt, { genSaltSync } from "bcrypt"; import fs from "fs"; export const config = { api: { bodyParser: false, }, }; // 将form.parse包装为Promise风格,确保异步逻辑可等待 const parseForm = (req) => { const form = formidable.IncomingForm(); return new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) reject(err); resolve({ fields, files }); }); }); }; const handlePost = async (req, res) => { try { const { fields, files } = await parseForm(req); await fileSavour(fields, files); return res.json({ message: "success", }); } catch (err) { // 出错时也返回响应,避免请求挂起 return res.status(500).json({ message: "操作失败", error: err.message }); } }; const fileSavour = async (fields, files) => { let { email, password } = fields; let imageName = files?.image?.name || ''; let newPassword = await bcrpt.hash(password, genSaltSync(10)); const newUser = new signupSchema({ email, password: newPassword, image: imageName, }); const Nuser = await newUser.save(); if (Nuser) { await mkdirp("public/profileImages/" + Nuser._id); if (imageName) { const data = fs.readFileSync(files.image.path); const pathToSave = "public/profileImages/" + Nuser._id + "/" + imageName; fs.writeFileSync(pathToSave, data); fs.unlinkSync(files.image.path); } } return; }; const Register = async (req, res) => { if (req.method === "POST") { // 加await等待handlePost执行完成 await handlePost(req, res); } else if (req.method === "PUT") { res.status(405).send(""); } else if (req.method === "DELETE") { res.status(405).send(""); } else if (req.method === "GET") { res.status(405).send(""); } else { res.status(404).send(""); } }; export default Register;
关键修改点
- 把回调风格的
form.parse封装为Promise,保证表单解析逻辑可被等待 Register函数中调用handlePost时添加await,确保整个请求处理逻辑执行完成后,API路由才会退出- 补充全局异常捕获,无论请求成功失败都返回对应响应,避免请求挂起
- 其他请求方法也补充了响应返回,避免无响应场景
内容的提问来源于stack exchange,提问作者nodeDev
相关产品推荐
相关产品推荐

