Node.js POST请求404问题:/upload接口需先提交出版物才可调用
Node.js POST接口404异常解决方案
登录后首次调用/upload接口返回「Cannot POST /upload」404错误,必须先调用/publicationaction接口后,所有POST接口才能正常工作。
问题根源分析
- 未定义全局变量导致服务器崩溃:两个接口均直接使用未声明的全局变量
facultyid(var Facultyid = facultyid;),首次请求/upload时该变量未初始化,触发ReferenceError导致服务器进程崩溃,此时所有接口无法响应,返回404。而调用/publicationaction时,该变量可能被意外初始化(如登录逻辑中全局赋值),接口可正常执行,服务器保持运行,后续请求能匹配到路由。 - 数据库连接滥用:每个接口处理函数内重复调用
connection.connect(),会导致数据库连接池耗尽或连接异常,间接引发服务不稳定。 - 缺乏错误捕获机制:接口逻辑未处理运行时异常,单个接口的错误会直接导致整个服务终止。
具体修复方案
1. 从Session中获取用户ID(替代全局变量)
登录后将用户ID存入req.session,接口中从session读取,而非依赖全局变量:
// /publicationaction接口修改 app.post('/publicationaction',upload.single('upload_proof'),function(req, res) { var Facultyid = req.session.facultyid; if (!Facultyid) { req.flash('message', '请先登录'); return res.redirect('/login'); } // 后续原有逻辑保持不变 }); // /upload接口修改 app.post('/upload',upload.single('upload_proof'),function(req, res) { var Facultyid = req.session.facultyid; if (!Facultyid) { req.flash('message', '请先登录'); return res.redirect('/login'); } // 后续原有逻辑保持不变 });
2. 全局初始化数据库连接
将数据库连接移至全局,避免每次请求重复连接:
// 在app初始化阶段执行数据库连接,而非接口处理函数内 var connection = require('./server'); connection.connect(function(error){ if(error) console.error('数据库连接失败:', error); else console.log('数据库连接成功'); }); // 接口处理函数中移除重复的connection.connect()调用,直接使用已连接的connection
3. 添加错误捕获与处理
在接口中添加try-catch捕获异常,避免服务崩溃:
app.post('/upload',upload.single('upload_proof'),function(req, res) { try { var Facultyid = req.session.facultyid; if (!Facultyid) { req.flash('message', '请先登录'); return res.redirect('/login'); } var title = req.body.title; var Url = req.body.url; var date = req.body.date; var Status = req.body.Status; var path = "No Data"; if (req.file?.path) { path = req.file.path; } var checkbox = req.body.checkbox; if(checkbox=='True') { var sql = "Insert into copyrights (facultyid,Title,Url,date,status,path,activitytime,action) VALUES ? ;Insert into log_data (activity,dateandtime) VALUES (?,?);"; var formatted = new Date().toISOString().slice(0, 19).replace('T', ' '); var values = [ [Facultyid, title, Url, date, Status, path, formatted, defaultaction] ]; connection.query(sql, [values, `${Facultyid} submitted copyrights`, formatted],function(err, result) { if (err) throw err; req.flash('message','Submitted Successfully'); res.redirect('/Copyrights'); }); } else { req.flash('message','Please Update the MIS'); res.redirect('/Copyrights'); } } catch(e) { console.error('接口错误:', e); req.flash('message','提交失败,请重试'); res.redirect('/Copyrights'); } });
4. 修正时间变量的生成
原代码中formatted是服务器启动时的固定时间,改为请求时的实时时间:
// 移除全局的dateTime定义,在需要时生成实时时间 var formatted = new Date().toISOString().slice(0, 19).replace('T', ' ');
额外优化建议
- 使用参数化查询避免SQL注入(原代码直接拼接字符串存在安全风险)
- 配置Express全局错误处理中间件:
app.use(function(err, req, res, next) { console.error(err.stack); req.flash('message','服务器内部错误'); res.redirect('/'); });
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

