节点 JS 不提供静态图像

Posted

技术标签:

【中文标题】节点 JS 不提供静态图像【英文标题】:Node JS not serving the static image 【发布时间】:2017-04-11 18:22:19 【问题描述】:

我已经添加了用于在我的节点服务器上提供图像的代码,但是在连接到 Node.js 时它似乎没有在 html 中提供图像。我也有正确提供的外部 CSS 和 JS。这是我在 Node 中的代码片段(见下文)。提前谢谢!

var server = http.createServer(function(req, res) 
    var pathname = url.parse(req.url).pathname;
    var ext = path.extname(pathname);
    var handler = handlers[req.url];
    if(ext) 
        if(ext === ".css")
            res.writeHead(200,  "Content-Type" : "text/css" );
        
        else if(ext === ".js") 
            res.writeHead(200,  "Content-Type" : "text/javascript" );
        
        else if(ext === ".jpg") 
            res.writeHead(200,  "Content-Type" : "image/jpg" );
        
        res.write(fs.readFileSync(__dirname + pathname, "utf8"));
        res.end();
    
    else if(handler) 
        handler(req, res);
    
    else 
        res.writeHead(404,  "Content-type" : "text/plain" );
        res.end();
    
);
server.listen(80);

【问题讨论】:

您可以在控制台中看到任何错误,例如 404? it seems to not serve images - “似乎没有”与“没有”有很大不同...检查 浏览器 开发人员工具控制台或网络选项卡以查看是否 a) 发出请求,b) 来自服务器的实际响应是什么(状态和内容 这无关紧要,但你真的不应该只是盲目地根据用户输入从磁盘提供文件(有人可以请求/../../../../../<some absolute path here with any extension>)。将所有公共文件放入您想要的任何层次结构中的某个目录中,但请确认最终 resolved 路径不在该基本公共目录之外。 我建议您添加一个console.log(__dirname + pathname) 并查看这是否是所需的文件名。另外,您不想使用utf8 编码读取二进制文件,也不想使用同步I/O。可能想读这个How to serve an image using nodejs。 Aruna:不,我没有收到这样的错误,但我在 html 中看到的是在加载图像时。 JaromandaX:图片不提供,对不起我的语法,我会检查控制台和网络日志。 mscdex:好的,请注意。我刚开始学习这项技术。 jfriend00:我将删除代码中的 utf8,并为该目录和路径名生成控制台日志。 【参考方案1】:

当有人尝试实现自己的静态文件服务器而不是使用 Express 或其他有效的东西但无法使其正常工作时,我在 Stack Overflow 上看到了很多类似的问题。如果您可以实现自己的静态文件服务器,那就去做吧。如果你不能,那么这应该表明这可能不是一个好主意。 更新:关于没有 Express 的解决方案,请参见下文。

问题

只要看一眼你的代码,我就已经看到了几个严重的问题,包括:

    您的代码不安全 - 它允许任何人获取您系统上的任何文件。

    您的代码阻塞 - 一旦您获得任何并发连接,它就会停止运行。

    您的代码不适用于二进制文件 - 仅适用于文本文件,并且仅适用于 UTF-8 编码的文件

    您的代码不适用于大写文件名.jpeg 扩展名等。

    您的代码未正确提供 HTML 文件

    当文件不存在而不是用正确的代码响应时,您的代码崩溃

解决方案

回答此类问题的任何人都有两种选择:要么投入大量精力和时间来解决上述每一个问题(这种情况很少发生,因为这不是一项微不足道的任务,这就是为什么你看到的都是 cmets提到其中的一两个问题而不是答案)您可以解释应该如何正确完成任务,而不是对一开始就不是一个好主意的事情添加无数修复。

话虽如此,要以安全且高效的方式实现您的目标,您可以将静态文件(HTML、CSS、图像等)放入一个目录中,例如调用html 并使用Express(或其他一些框架,见下文)和这样的简单代码:

var path = require('path');
var express = require('express');
var app = express();

var htmlPath = path.join(__dirname, 'html');

app.use(express.static(htmlPath));

var server = app.listen(80, function () 
    console.log('listening on port', server.address().port);
);

在 GitHub 上查看完整示例和解释:

https://github.com/rsp/node-express-static-example

我把这个例子放在 GitHub 上,因为 Stack Overflow 上有很多与人们在 Node.js 中提供静态文件有关的问题。它是开源的,您可以根据自己的需要对其进行调整并在您的代码中使用。

有关 Express 的更多信息,请参阅:

http://expressjs.com/en/4x/api.html

其他选项

可用于提供静态文件的其他框架包括:

koa、Restify、Hapi、Sails、LoopBack 和 more。

没有框架

如果您仍然认为您不想使用能够正确完成工作的高级框架并且您想推出自己的解决方案,也许是出于教育目的,那么请查看以下答案:

How to serve an image using nodejs

它解释了如何提供静态图像:

    express.staticexpress 内置中间件,就像这个答案) expressexpress 但没有express.staticconnect(比express低一级) http(使用 Node 的 http 模块) net(甚至不使用 http 模块)

发布的所有示例都经过测试,可在 Node 版本 4、5、6 和 7 上运行。

其他相关答案:

How to serve an image using nodejs Failed to load resource from same directory when redirecting Javascript onload js call not working with node Sending whole folder content to client with express Loading partials fails on the server JS

【讨论】:

您的回答真的很有帮助,非常感谢!我才刚刚开始研究这项技术,我的任务是不使用框架而只使用纯 Javascript。我还不知道列出我的代码的问题。我稍后会检查链接以获取更多信息。 我通过删除 res.write(fs.readFileSync(__dirname + pathname, "utf8")) 上的“utf8”来修复它; @Cham 如果您不想使用框架,请查看我的更新答案和this。希望对您有所帮助。

以上是关于节点 JS 不提供静态图像的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的节点静态文件服务器丢弃请求?

如何使图像围绕静态徽标旋转?

Vue-cli 生产版本不显示静态图像

如何使用 Iron 路由器提供静态内容(图像、字体等)

如何上传静态文件(图像、文档)?

Webpack和webpack dev服务器不提供静态文件