sendFile绝对路径

168
如果我执行一个

res.sendfile('public/index1.html'); 

我收到了服务器控制台警告:

express已弃用res.sendfile,请改为使用res.sendFile

但在客户端方面它仍然正常工作。

当我将其更改为:

res.sendFile('public/index1.html');

我遇到了一个错误:

类型错误:路径必须是绝对路径或指定根目录才能使用 res.sendFile

而且无法渲染 index1.html

我无法确定绝对路径是什么。我在与 server.js 相同的级别上有一个名为 public 的目录。我正在 server.js 中使用 res.sendFile。我还声明了 app.use(express.static(path.join(__dirname, 'public')));

以下是我的目录结构:

/Users/sj/test/
....app/
........models/
....public/
........index1.html

这里需要指定什么绝对路径?
我正在使用Express 4.x。

如果您正在使用express.static中间件来提供公共目录,为什么需要使用res.sendFile来发送public/index1.html - Mike S
2
我正在从app.get('/', function(req, res){res.sendFile("...")})中调用res.sendFile以按需发送它。 - Kaya Toast
13个回答

364
express.static 中间件与 res.sendFile 是分开的,因此使用绝对路径初始化 public 目录并不会影响 res.sendFile。你需要直接在 res.sendFile 中使用绝对路径。有两种简单的方法可以实现:
  1. res.sendFile(path.join(__dirname, '../public', 'index1.html'));
  2. res.sendFile('index1.html', { root: path.join(__dirname, '../public') });
注意:__dirname 返回当前执行脚本所在的目录。在您的情况下,看起来 server.jsapp/ 目录中。因此,要进入 public,您需要先返回上一级:../public/index1.html 注意: path 是一个内置的模块,需要在上述代码中使用 requirevar path = require('path');

27
res.sendFile('../public/index.html', {root: __dirname}); 也可以使用,而且更短。 - Fabien Sa
使用Express和WebStorm IDE:在console.log(path.join(__dirname,'../public','index.html'));中没有错误,但是只有在var path = require('path');的情况下才能使用res.sendFile(path.join(__dirname,'../public','index.html')); - Quake1TF
1
有没有办法预定义绝对路径,以便在sendFile中使用? - eran otzap
4
res.sendFile('../public/index.html', {root: __dirname});不再起作用,因为它会超出根目录而返回403 Forbidden错误。请改为使用res.sendFile('public/index.html', {root: path.dirname(__dirname)}); - Trevor Robinson
@eranotzap 而且 app.use(express.static('public')) 应该首先是一个查找路径,不是吗? - undefined

59

不妨试试这个:

res.sendFile('public/index1.html' , { root : __dirname});

这对我有用。 根目录: __dirname将获取上面示例中server.js所在的地址,然后为了到达index1.html(在本例中),返回的路径是到达public文件夹所在目录。


为什么这个选项没有记录? - timkay

12

一个尚未列出的替代方案适用于我,就是简单地使用 path.resolve,无论是分开的字符串还是一个包含整个路径的字符串:

// comma separated
app.get('/', function(req, res) {
    res.sendFile( path.resolve('src', 'app', 'index.html') );
});

或者

// just one string with the path
app.get('/', function(req, res) {
    res.sendFile( path.resolve('src/app/index.html') );
});

(Node v6.10.0)

灵感来源于https://dev59.com/7WUq5IYBdhLWcg3wT-2D#14594282


10
res.sendFile( __dirname + "/public/" + "index1.html" );

__dirname会管理当前执行的脚本(server.js)所在的目录名称。


这个解决方案非常直接,感谢帮助...我想知道为什么人们推荐使用“path”包来做同样的事情。 - The Third
3
我想,使用“path”可以使其与操作系统无关。 - kmonsoor

9

根据其他回答,这是一个简单的例子,说明如何完成最常见的要求:

const app = express()
app.use(express.static('public')) // relative path of client-side code
app.get('*', function(req, res) {
    res.sendFile('index.html', { root: __dirname })
})
app.listen(process.env.PORT)

这也可以用作一种简单的方式来响应每个请求,并在此过程中作为对index.html的响应,因为我使用星号*来捕获在您的静态(公共)目录中未找到的所有文件;这是Web应用程序最常见的用例。将其更改为/以仅在根路径中返回索引。

好的。简洁明了。 - lharby

6

process.cwd() 返回您的项目的绝对路径。

然后:

res.sendFile( `${process.cwd()}/public/index1.html` );

5
我试过了,它有效。
app.get('/', function (req, res) {
    res.sendFile('public/index.html', { root: __dirname });
});

3

你可以使用 send 代替 sendFile,这样你就不会遇到错误了!这个方法能够帮助你解决问题!

fs.readFile('public/index1.html',(err,data)=>{
if(err){
  consol.log(err);
}else {
res.setHeader('Content-Type', 'application/pdf');

告诉浏览器你的响应是PDF类型的方法
res.setHeader('Content-Disposition', 'attachment; filename='your_file_name_for_client.pdf');

如果您想让用户下载后立即在同一页上打开该文件,请在上述代码中使用“inline”而不是“attachment”。

res.send(data)

2

如果您想在各处设置一次并随时使用,只需配置自己的中间件。当您设置应用程序时,请使用以下内容在响应对象上定义一个新函数:

app.use((req, res, next) => {
  res.show = (name) => {
    res.sendFile(`/public/${name}`, {root: __dirname});
  };
  next();
});

然后按以下方式使用它:
app.get('/demo', (req, res) => {
  res.show("index1.html");
});

2

通过写更少的代码,还有一种方法可以实现这个目标。

app.use(express.static('public'));

app.get('/', function(req, res) {
   res.sendFile('index.html');
});

8
这会生成“TypeError: 路径必须是绝对的或者需要指定根目录以便使用 res.sendFile”错误。 - GreenAsJade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接