如何使用nodejs提供图像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用nodejs提供图像相关的知识,希望对你有一定的参考价值。

我有一个位于public / images / logo.gif的徽标。这是我的nodejs代码。

http.createServer(function(req, res){
  res.writeHead(200, {'Content-Type': 'text/plain' });
  res.end('Hello World 
');
}).listen(8080, '127.0.0.1');

它工作,但当我要求localhost:8080 / logo.gif然后我显然我没有得到徽标。

我需要做些什么来改变图像。

答案

2016 Update

Express和without Express实际工作的示例

这个问题超过5年,但每个答案都有一些问题。

TL; DR

向下滚动以查看示例以提供图像:

  1. express.static
  2. express
  3. connect
  4. http
  5. net

所有的例子都在GitHub上:https://github.com/rsp/node-static-http-servers

测试结果可在Travis:https://travis-ci.org/rsp/node-static-http-servers上获得

介绍

自从这个问题被问到5年后,只有one correct answer by generalhenry但是即使答案对代码没有问题,它似乎也有一些接收问题。有人评论说,除了如何依靠别人完成工作之外,“并没有解释太多”,而且有多少人投票评论这个评论清楚地表明很多事情需要澄清。

首先,对“如何使用Node.js提供图像”的一个很好的答案是没有从头开始实现静态文件服务器并且做得很糟糕。一个很好的答案是使用像Express这样的模块来正确地完成工作。

回答评论说使用Express“除了如何依赖别人完成工作之外没有解释太多”应该注意,使用http模块已经依赖于其他人来完成工作。如果有人不想依赖任何人完成工作,那么至少应该使用原始的TCP套接字 - 我在下面的一个例子中做了这个。

一个更严重的问题是,使用http模块的所有答案都被打破了。它们引入了竞争条件,不安全的路径解析将导致路径遍历漏洞,阻止完全无法满足任何并发请求的I / O以及其他微妙的问题 - 它们完全被打破,作为问题所要求的示例,以及但是他们已经使用http模块提供的抽象而不是使用TCP套接字,因此他们甚至不会像他们声称的那样从头做任何事情。

如果问题是“如何从头开始实现静态文件服务器,作为一种学习练习”那么通过各种方式回答如何做到这一点应该被发布 - 但即便如此,我们也应该期望它们至少是正确的。此外,假设想要提供图像的人可能希望将来提供更多图像是不合理的,因此可以争辩说编写一个特定的自定义静态文件服务器,只能为一个具有硬编码路径的文件提供服务,有些短视。似乎很难想象任何搜索如何提供图像的答案的人都会满足于只提供单个图像的解决方案,而不是为任何图像提供服务的通用解决方案。

简而言之,问题是如何提供图像,并且答案是使用适当的模块以安全,预先形成且可靠的方式执行此操作,这种方式在使用专业节点的最佳实践时是可读的,可维护的且面向未来的发展。但我同意,对这样一个答案的一个很好的补充就是展示了一种手动实现相同功能的方法,但遗憾的是,到目前为止,每次尝试这样做都失败了。这就是为什么我写了一些新的例子。

在这个简短的介绍之后,这里是我在五个不同抽象层次上完成工作的五个例子。

最低功能

每个示例都提供来自qazxsw poi目录的文件,并支持以下最小功能:

  • 大多数常见文件的MIME类型
  • 提供html,JS,CSS,纯文本和图像
  • public作为默认目录索引
  • 响应丢失文件的错误代码
  • 没有路径遍历漏洞
  • 阅读文件时没有竞争条件

我在Node版本4,5,6和7上测试了每个版本。

index.html

此版本使用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中间件。服务静态文件使用流实现为单个路由处理程序。

此示例具有简单的路径遍历对策,并支持一组有限的最常见MIME类型。

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版本类似的功能,但使用稍低杠杆的API。

express

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模块,该模块是Node中HTTP的最低级API。

此示例具有与http版本类似的功能,但使用更低级别的API。

connect

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模块,该模块是Node中TCP套接字的最低级API。

此示例具有net版本的一些功能,但最小和不完整的HTTP协议已从头开始实现。由于它不支持分块编码,因此在发送响应之前将文件加载到内存中之前知道大小,因为定位文件然后加载会引入竞争条件。

http

下载示例

我在GitHub上发布了所有的例子,并附有更多解释。

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(/ ? ?/)) { var line = input.split(/ /)[0].split(' '); var method = line[0], url = line[1], pro = line[2];

以上是关于如何使用nodejs提供图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 NodeJS 和 JSDOM/jQuery 从代码片段构建 PHP 页面

如何从Android片段中的相机获取图像

如何从片段中检索gridview中的图像?

如何使用 nodejs 获取 gif 图像帧的 base64?

自定义对话框片段

如何使用 NodeJS 和 puppeteer 从 udemy 抓取图像