为何非主app.js调用res.sendFile无法访问__dirname + "/../public"?
问题原因及解决方案
核心原因
问题出在__dirname的作用域差异以及res.sendFile的安全限制:
- 代码在
app.js中时,__dirname指向项目根目录,拼接出的文件路径属于根目录范围内,res.sendFile默认允许访问该目录下的文件。 - 逻辑拆分到
src/bug-reporter.js后,__dirname指向src文件夹,拼接后的路径__dirname + '/../public/bug-reporter/bugs.html'会跳出src目录,而res.sendFile的默认安全机制会阻止访问当前模块目录之外的文件(防范路径遍历攻击),因此抛出ForbiddenError: Forbidden。
解决方案
方案一:利用入口文件路径获取项目根目录
require.main.path会返回项目入口文件(app.js)所在的目录,直接用它作为res.sendFile的root参数:
// src/bug-reporter.js const path = require('path'); exports.home = (req, res) => { // 获取项目根目录 const rootDir = require.main.path; res.sendFile('public/bug-reporter/bugs.html', { root: rootDir }); };
方案二:从入口模块传递根目录
在app.js中把项目根目录传递给子模块,避免依赖require.main:
// app.js const bugReporter = require('./src/bug-reporter')(__dirname); app.get('/bug-reporter/', bugReporter.home);
// src/bug-reporter.js module.exports = (rootDir) => { return { home: (req, res) => res.sendFile('public/bug-reporter/bugs.html', { root: rootDir }) }; };
方案三:用path.resolve拼接绝对路径并指定root
通过path.resolve生成绝对路径,同时明确指定文件所在目录为root:
// src/bug-reporter.js const path = require('path'); exports.home = (req, res) => { const filePath = path.resolve(__dirname, '../public/bug-reporter/bugs.html'); res.sendFile(filePath, { root: path.dirname(filePath) }); };
内容的提问来源于stack exchange,提问作者Nikolay Dyankov
相关产品推荐
相关产品推荐

