- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个位于public / images / logo.gif的徽标。这是我的nodejs代码。
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain' });
res.end('Hello World \n');
}).listen(8080, '127.0.0.1');
最佳答案
2016更新
使用Express和不使用Express的示例实际有效
这个问题已有5年历史了,但是每个答案都有一些问题。
TL; DR
向下滚动示例以使用以下图片投放图片:express.static
express
connect
http
net
所有示例也都在GitHub上:https://github.com/rsp/node-static-http-servers
测试结果在Travis上可用:https://travis-ci.org/rsp/node-static-http-servers
介绍
自从问了这个问题5年多之后,通俗查询只给出了one correct answer,但是即使该回答在代码上没有问题,也似乎在接收方面存在一些问题。有人评论说,“除了如何依靠别人来完成工作外,它没有其他解释”,事实上,有多少人投票赞成该评论,这表明很多事情需要澄清。
首先,“如何使用Node.js提供图像”的一个很好的答案不是从头开始实现静态文件服务器,而是做得不好。一个很好的答案是使用像Express这样的模块来正确地完成工作。
回答说使用Express“除了如何依靠别人来完成工作外,并没有其他解释”,应该指出,使用http
模块已经依赖于别人来完成工作。如果某人不想依靠任何人来完成工作,则至少应使用原始TCP套接字代替-我在下面的示例之一中进行了此操作。
一个更严重的问题是,所有使用http
模块的答案都被破坏了。它们引入了竞争条件,不安全的路径解析(将导致路径穿越漏洞),阻止将完全无法满足所有并发请求以及其他细微问题的I / O-它们被完全破坏为问题的示例,并且但是他们已经使用了http
模块提供的抽象,而不是使用TCP套接字,因此他们甚至没有像声称的那样从头开始做所有事情。
如果问题是“作为学习练习,如何从头开始实现静态文件服务器”,则应通过各种方式回答应该发布的内容-但是即使如此,我们也应该期望它们至少是正确的。同样,并非毫无道理地假设某人想要提供图像,将来可能会提供更多图像,因此有人可能会认为编写特定的自定义静态文件服务器只能提供一个带有硬编码路径的单个文件,这是合理的。有点短视。似乎很难想象,谁能找到有关如何提供图像的答案,那么他们将对仅提供单个图像的解决方案而不是提供任何图像的通用解决方案感到满意。
简而言之,问题是如何为图像提供服务,而对此的答案是使用适当的模块以安全,高效,可靠的方式做到这一点,该方式具有可读性,可维护性和面向未来,同时使用专业Node的最佳实践发展。但是我同意,对这种答案的一个很好的补充将是展示一种手动实现相同功能的方法,但遗憾的是,到目前为止,每次尝试都失败了。这就是为什么我写了一些新的例子。
简短介绍之后,下面是我的五个示例,分别在5个不同的抽象级别上进行工作。
最低功能
每个示例都提供public
目录中的文件,并支持以下最低功能:
最常见文件的MIME类型
提供HTML,JS,CSS,纯文本和图像
将index.html
用作默认目录索引
响应错误代码以查找丢失的文件
没有路径遍历漏洞
读取文件时没有比赛条件
我在Node版本4、5、6和7上测试了每个版本。express.static
此版本使用express.static
模块的express
内置中间件。
此示例具有最多的功能和最少的代码量。
var path = require('path');
var express = require('express');
var app = express();
var dir = path.join(__dirname, 'public');
app.use(express.static(dir));
app.listen(3000, function () {
console.log('Listening on http://localhost:3000/');
});
express
express
模块,但没有
express.static
中间件。服务静态文件使用流作为单个路由处理程序实现。
var path = require('path');
var express = require('express');
var app = express();
var fs = require('fs');
var dir = path.join(__dirname, 'public');
var mime = {
html: 'text/html',
txt: 'text/plain',
css: 'text/css',
gif: 'image/gif',
jpg: 'image/jpeg',
png: 'image/png',
svg: 'image/svg+xml',
js: 'application/javascript'
};
app.get('*', function (req, res) {
var file = path.join(dir, req.path.replace(/\/$/, '/index.html'));
if (file.indexOf(dir + path.sep) !== 0) {
return res.status(403).end('Forbidden');
}
var type = mime[path.extname(file).slice(1)] || 'text/plain';
var s = fs.createReadStream(file);
s.on('open', function () {
res.set('Content-Type', type);
s.pipe(res);
});
s.on('error', function () {
res.set('Content-Type', 'text/plain');
res.status(404).end('Not found');
});
});
app.listen(3000, function () {
console.log('Listening on http://localhost:3000/');
});
connect
connect
模块,该模块比
express
低一个抽象级别。
express
版本相似的功能,但使用了稍低一些的API。
var path = require('path');
var connect = require('connect');
var app = connect();
var fs = require('fs');
var dir = path.join(__dirname, 'public');
var mime = {
html: 'text/html',
txt: 'text/plain',
css: 'text/css',
gif: 'image/gif',
jpg: 'image/jpeg',
png: 'image/png',
svg: 'image/svg+xml',
js: 'application/javascript'
};
app.use(function (req, res) {
var reqpath = req.url.toString().split('?')[0];
if (req.method !== 'GET') {
res.statusCode = 501;
res.setHeader('Content-Type', 'text/plain');
return res.end('Method not implemented');
}
var file = path.join(dir, reqpath.replace(/\/$/, '/index.html'));
if (file.indexOf(dir + path.sep) !== 0) {
res.statusCode = 403;
res.setHeader('Content-Type', 'text/plain');
return res.end('Forbidden');
}
var type = mime[path.extname(file).slice(1)] || 'text/plain';
var s = fs.createReadStream(file);
s.on('open', function () {
res.setHeader('Content-Type', type);
s.pipe(res);
});
s.on('error', function () {
res.setHeader('Content-Type', 'text/plain');
res.statusCode = 404;
res.end('Not found');
});
});
app.listen(3000, function () {
console.log('Listening on http://localhost:3000/');
});
http
http
模块,该模块是Node中HTTP的最低级别的API。
connect
版本相似的功能,但使用的是更低级的API。
var path = require('path');
var http = require('http');
var fs = require('fs');
var dir = path.join(__dirname, 'public');
var mime = {
html: 'text/html',
txt: 'text/plain',
css: 'text/css',
gif: 'image/gif',
jpg: 'image/jpeg',
png: 'image/png',
svg: 'image/svg+xml',
js: 'application/javascript'
};
var server = http.createServer(function (req, res) {
var reqpath = req.url.toString().split('?')[0];
if (req.method !== 'GET') {
res.statusCode = 501;
res.setHeader('Content-Type', 'text/plain');
return res.end('Method not implemented');
}
var file = path.join(dir, reqpath.replace(/\/$/, '/index.html'));
if (file.indexOf(dir + path.sep) !== 0) {
res.statusCode = 403;
res.setHeader('Content-Type', 'text/plain');
return res.end('Forbidden');
}
var type = mime[path.extname(file).slice(1)] || 'text/plain';
var s = fs.createReadStream(file);
s.on('open', function () {
res.setHeader('Content-Type', type);
s.pipe(res);
});
s.on('error', function () {
res.setHeader('Content-Type', 'text/plain');
res.statusCode = 404;
res.end('Not found');
});
});
server.listen(3000, function () {
console.log('Listening on http://localhost:3000/');
});
net
net
模块,该模块是Node中TCP套接字的最低级别的API。
http
版本的某些功能,但是最小和不完整的HTTP协议已从头开始实现。由于它不支持分块编码,因此在发送响应之前先将文件加载到内存中,然后再知道它们的大小,因为先声明文件然后加载会引入竞争条件。
var path = require('path');
var net = require('net');
var fs = require('fs');
var dir = path.join(__dirname, 'public');
var mime = {
html: 'text/html',
txt: 'text/plain',
css: 'text/css',
gif: 'image/gif',
jpg: 'image/jpeg',
png: 'image/png',
svg: 'image/svg+xml',
js: 'application/javascript'
};
var server = net.createServer(function (con) {
var input = '';
con.on('data', function (data) {
input += data;
if (input.match(/\n\r?\n\r?/)) {
var line = input.split(/\n/)[0].split(' ');
var method = line[0], url = line[1], pro = line[2];
var reqpath = url.toString().split('?')[0];
if (method !== 'GET') {
var body = 'Method not implemented';
con.write('HTTP/1.1 501 Not Implemented\n');
con.write('Content-Type: text/plain\n');
con.write('Content-Length: '+body.length+'\n\n');
con.write(body);
con.destroy();
return;
}
var file = path.join(dir, reqpath.replace(/\/$/, '/index.html'));
if (file.indexOf(dir + path.sep) !== 0) {
var body = 'Forbidden';
con.write('HTTP/1.1 403 Forbidden\n');
con.write('Content-Type: text/plain\n');
con.write('Content-Length: '+body.length+'\n\n');
con.write(body);
con.destroy();
return;
}
var type = mime[path.extname(file).slice(1)] || 'text/plain';
var s = fs.readFile(file, function (err, data) {
if (err) {
var body = 'Not Found';
con.write('HTTP/1.1 404 Not Found\n');
con.write('Content-Type: text/plain\n');
con.write('Content-Length: '+body.length+'\n\n');
con.write(body);
con.destroy();
} else {
con.write('HTTP/1.1 200 OK\n');
con.write('Content-Type: '+type+'\n');
con.write('Content-Length: '+data.byteLength+'\n\n');
con.write(data);
con.destroy();
}
});
}
});
});
server.listen(3000, function () {
console.log('Listening on http://localhost:3000/');
});
express.static
,
express
,
connect
,
http
和
net
的示例:
express.static
的其他项目:
关于node.js - 如何使用Node.js提供图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52359785/
我用运行 Node node --debug app OR node --debug-brk app 它有反应 debugger listening on port 5858 Express serv
这个问题在这里已经有了答案: What is the difference between (int *i) and (int* i) in context of both C and C++? [
我有一个应用程序,它通过消息队列将数据库写入命令分派(dispatch)给工作人员(数量非常大),因此无法保证它们的接收顺序。 我有两个 Node ,例如“Account”和“Media”。在此假设的
有没有办法在调用 ts-node 时将选项传递给 Node ?我正在尝试在 Node 中使用一个实验性功能,如果它能与 ts-node 一起使用,那就太好了。 这就是我目前正在做的事情: ts-nod
我有一个容器化的Node应用程序,它在DigitalOcean服务器上运行。当我更新服务器上的应用程序时,该应用程序必须关闭一小段时间。为了能够更新应用程序并避免停机,我目前正在阅读零停机时间部署/蓝
我正在编写一个 Node.js 应用程序。我正在使用 request 和 Cheerio 加载一组 URL 并获取该网站的大量信息,现在假设我想要获取的只是标题: var urls = {"url_1
如果不弹出以下错误,我无法安装任何 Node.js 模块。错误代码引用package.json文件。如果知道为什么会发生这种情况,我们将不胜感激。 最佳答案 这些不是错误,它们只是警告。一切都应该如此
如果我运行(从我的项目目录中): supervisor javascripts/index.js 我得到:/usr/bin/env: Node :没有这样的文件或目录 如果我运行: node java
我已遵循使用 Node-Inspector 的所有步骤 但是当我打开应用程序时,我在控制台上看不到任何脚本或日志。 我的应用程序在端口 4000 上运行。我认为唯一可能发生冲突的是端口 8080 上的
我在android中使用rxjava2,有时会遇到这样的问题: Observable.fromArray( // maybe a list about photo url in SD
我目前正在使用 Node 光纤来编写同步服务器端代码。我主要通过 try-catch block 进行错误处理,但外部库或其他小部分异步代码中总是有可能发生错误。我正在考虑使用新的域功能来尝试将这些错
看起来node-debug是node-inspector周围的一个shell?分别什么时候应该使用? 最佳答案 如果您安装node-debug,您只能访问node-debug命令。 如果您安装node
我目前正在代理后面工作,该代理不允许我执行此命令的 HTTP GET 请求阶段: Node node-sass/scripts/build.js 请求阶段: gyp http GET https://
听说node js可以用在服务端。我以前用过jsp。 jsp页面内部的java代码对客户端是不可见的。如果 Node js 只是 javascript,那么它如何对客户端不可见? 最佳答案 首先,No
我正在为 Node native 插件从 node-waf 构建迁移到 node-gyp 构建系统。 node-gyp 说它支持多个目标版本,但我在使用 node-gyp 时找不到如何指定目标 Nod
给定一个 $node ,我正在尝试在以下两种输出该 $node 的方式之间做出决定。 要么 $output = theme('node', $node); 或 node_build_content($
如果package.json中的窗口A打开一个新窗口B,node-main如何访问它?这是我的代码: package.json { "main": "index.html",
我试图在我的 xml 中的特定节点 ( ) 之前插入一个注释节点。这是它的方法: function test(xmlResponse) { var parser = new DOMParse
我正在尝试做npm install wrtc使用 Node 版本 16.14.0 但这还没有完成。它在给npm error code 1所以我试图将 Node 版本更改为以前的 lts 14.19.0
当我在 Visual Studio 中运行 Node.js 应用程序时,我收到以下消息:DeprecationWarning: 'node --debug' 和 'node --debug-brk'
我是一名优秀的程序员,十分优秀!