Node.js Express中app.post内调用res.sendFile无响应(状态码200)
问题分析与解决方案
核心问题
你的代码存在四个关键问题导致res.sendFile无响应:
- 全局变量
user_name引发并发冲突:多个用户同时提交时,全局变量会被覆盖,导致名称重复判断逻辑失效。 readFileSync错误用法:同步读取文件时传入了回调函数,且未捕获读取/JSON解析异常,一旦出错会直接终止代码执行,无法返回响应。res.sendFile未处理错误:若文件路径错误或文件不存在,res.sendFile不会主动返回错误响应,客户端会一直等待。- 正常提交分支无响应返回:名称不重复时,路由未向客户端返回任何响应,导致请求挂起。
修复步骤
1. 替换全局变量为Session存储
全局变量无法区分不同用户,改用express-session存储用户信息:
- 安装依赖:
npm install express-session - 配置Session中间件:
import session from 'express-session'; // 配置session,生产环境需调整secret和cookie参数 app.use(session({ secret: 'your-custom-secret-key', // 替换为你的密钥 resave: false, saveUninitialized: true, cookie: { secure: false } // 本地开发用false,生产环境HTTPS下改为true }));
- 修改
POST /name路由:
app.post("/name", (req, res) => { req.session.user_name = req.body.name; // 存入session console.log("name: ", req.body.name); res.sendFile(__dirname + "/public/play.html"); });
2. 修复readFileSync用法
同步读取文件无需回调,且需捕获异常避免服务器崩溃:
// 替换原读取文件代码 let data; try { data = readFileSync("./data/scores.json", 'utf8'); // 指定编码为utf8 } catch (error) { console.log(error); return res.status(500).send('读取分数文件失败'); }
3. 给res.sendFile添加错误处理
确保文件不存在时返回错误响应:
if (names.includes(user_name)) { console.log("Name used already!"); res.sendFile(__dirname + "/public/dup_name.html", (err) => { if (err) { console.error('返回重复名称页面失败:', err); res.status(err.status || 500).send('页面加载失败'); } }); return; };
4. 正常提交分支添加响应返回
名称不重复时,文件写入完成后向客户端返回响应:
writeFile("./data/scores.json", JSON.stringify(scores_data), (error) => { if (error) { console.log("保存分数失败: ", error); return res.status(500).send('保存分数失败'); } console.log("Data written successfully to the file"); res.sendFile(__dirname + "/public/success.html"); // 替换为你的成功页面,或返回文本 });
修改后的完整/publish-score路由代码
app.post("/publish-score", (req, res) => { const user_name = req.session.user_name; // 从session获取用户名 const user_score = req.body.score; console.log("request name: ", user_name); console.log("request score: ", user_score); // 读取分数文件 let data; try { data = readFileSync("./data/scores.json", 'utf8'); } catch (error) { console.log(error); return res.status(500).send('读取分数文件失败'); } // 检查名称是否重复 let scores_data; try { scores_data = JSON.parse(data); } catch (parseError) { console.error('解析JSON失败:', parseError); return res.status(500).send('分数文件格式错误'); } const names = scores_data.daily_puzzle.scores.map(entry => entry.name); console.log("names: ", names); if (names.includes(user_name)) { console.log("Name used already!"); res.sendFile(__dirname + "/public/dup_name.html", (err) => { if (err) { console.error('返回重复名称页面失败:', err); res.status(err.status || 500).send('页面加载失败'); } }); return; }; // 处理空值 const push_name = user_name ?? "NoName"; const push_score = user_score ?? "NoScore"; scores_data.daily_puzzle.scores.push({ "name": push_name, "score": push_score }); // 写入文件并返回响应 writeFile("./data/scores.json", JSON.stringify(scores_data), (error) => { if (error) { console.log("保存分数失败: ", error); return res.status(500).send('保存分数失败'); } console.log("Data written successfully to the file"); res.sendFile(__dirname + "/public/success.html"); // 替换为实际成功页面路径 }); });
内容的提问来源于stack exchange,提问作者Seth Strumwasser
相关产品推荐
相关产品推荐

