Node.js提供HTML页面和静态内容服务

3
var express = require("express");
var app     = express();
var path    = require("path");

app.use(express.static(__dirname + '/view'));

app.get('/dashboard',function(req,res){
  res.sendFile((path.join(__dirname + '/dashboard.html'));
});

app.get('/index1',function(req,res){
  res.sendFile((path.join(__dirname+'/index.html'));
});
app.get('/',function(req,res){
  res.redirect('/login');
});
app.get('/login',function(req,res){
  res.redirect((path.join(__dirname + '/login'));
});

app.listen(3000);

console.log("Running at Port 3000");

我的问题是为什么每次都要检查用户请求的内容?

另外,如果我在目录中有100个html文件,我需要通过get方法检查每个文件,然后通过res.sendFile返回页面吗?


5
所有网络服务器都是这样工作的。当你浏览目录时,甚至你的操作系统也是这样工作的。什么让你认为有一种神奇的方式可以在不检查用户输入内容的情况下确定用户想要什么? - slebetman
尽管@slebetman所说的完全正确,但是我认为OP出于某种原因认为他们必须列出每个静态文件,而不是创建一个文件服务中间件。 - Clemens Himmer
@ClemensHimmer:啊,我看到了静态中间件并以为他在问为什么静态中间件需要每次请求都检查URL。因为他的问题是“用户每次请求的内容”,而不是每个路径提供的内容。我的错。 - slebetman
3个回答

5
@OrangeDog和@Clemens Himmer所说的都是正确的。然而,最简单的方法来提供目录中的所有文件已经在您的脚本中了:
app.use(express.static(__dirname + '/view'));

如果名称与URL匹配,它将服务于您的view目录中的所有内容,例如http://yoursite.com/index.html将解析为 __dirname+'/view/index.html' 的文件。

但是,在您的示例路由中,似乎您正在更改URL路径以不再与文件位置匹配(例如,您希望/login解析为'/login.html')。 您肯定可以编写中间件来修改和基于模式解析文件,但此时使用专门构建的Web服务器(如先前建议的nginx)更加简单,因为它已经具备URL重写功能。


你说得对,也许最好坚持基础知识,因为原帖作者似乎在理解Web服务器的基础知识方面有困难,简单易懂是加分项。 - Clemens Himmer

3
不,您不必以编程方式列出所有静态文件。您可以通过将middleware绑定到服务器根目录来动态地提供它们。
这是我完成的一个小的express.js脚本,基本上是一个非常简单的Web服务器,可以提供任何内容和漂亮的HTML。
// This servers a file..
var serveFile = function(filePath, res){
    var options = {
        dotfiles: 'deny',
        headers: {
            'x-timestamp': Date.now(),
            'x-sent': true
        }
    };

    res.sendFile(filePath, options, function (err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        }
    });
};

// Serve web files
app.use("/", function (req, res, next) {

    var filePath = (absoluteServePath + req.originalUrl).replace(/\//g,"\\");

    var checkFilePath = function(filePath){
        return new Promise(function(resolve, reject) {
            fs.access(filePath, fs.F_OK, function(err) {
                if(!err){
                    // If FILE / DIR exists check if file or DIR
                    if(fs.lstatSync(filePath).isDirectory() == true){
                        reject();
                    }
                    else{
                        resolve();
                    }

                }else{
                    reject(err);
                }
            });
        });
    };

    checkFilePath(filePath).then(function(){
        serveFile(filePath,res);
    },function(){
        // Check if path ends with a slash
        var endsWithSlash = filePath.substr(filePath.length - 1) == "\\";
        // Check if a index.html exists in the path
        var indexHTMLPath = filePath + ((endsWithSlash == true) ? "" : "\\") + "index.html";

        checkFilePath(indexHTMLPath).then(function(){
            serveFile(indexHTMLPath,res);
        },function(){
            // Check if .html for the path exists
            var plusHTMLPath = filePath +".html";

            checkFilePath(plusHTMLPath).then(function(){
                serveFile(plusHTMLPath,res);
            },function(){
                // Nope, does not exist at all
                next();
            });
        });
    });
});

哦,绝对不是的,如果你能阅读带有评论和文本的内容,你应该能够完全理解这个答案的每一部分。 - Clemens Himmer
另外,我刚刚在代码中添加了一些注释,这是对我的帖子的补充,专门为你准备的。如果现在一个11k用户还看不出这段代码的作用,我会非常惊讶的 :) - Clemens Himmer
2
我能看出它的作用,但我不确定仅仅给OP一个完整的复制解决方案是否有帮助。 - OrangeDog

1
我的问题是为什么每次都需要检查用户请求的内容?
如果不检查用户请求的内容,你怎么能给他们想要的东西呢?
如果我的目录中有100个HTML文件,我是否需要通过get方法检查每个文件,然后通过res.sendFile返回页面?
如果你的意思是需要为每个文件声明一个单独的路由,那么答案是否定的。Express路由可以基于模式,因此您可以为整个目录定义一个路由,然后返回所请求的特定文件:Node中简单的静态HTML服务器
然而,所有这些都导致了Node.JS 不是用于提供大量静态内容的最佳选择。您需要注意许多安全和其他问题,并且它的性能并不像可能的那样好。如果您使用nginx或apache2服务器来提供这些文件并将动态请求转发到您的Node服务器,则可能会更好。

Node.js + Nginx - 现在怎么办?


我的问题是为什么每次都需要检查用户请求的内容?如果不检查用户请求的内容,你怎么能给他们想要的呢?为什么需要检查?比如说,如果我通过浏览器 URL 请求 index.html 文件,如果文件存在,它应该返回给我,否则就应该抛出错误。由于我是新手,所以我很困惑为什么需要检查。 - shaik
如果文件存在 - 这被称为检查。我认为你所说的“检查”实际上是定义路由,而我的答案的第二部分涵盖了这一点。 - OrangeDog
从根本上讲,除非您检查,否则无法确定“index.html”是否是您要查找的内容。但正如我所说,我认为您只是使用了错误的词汇并且让自己感到困惑。 - OrangeDog

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