gpt4 book ai didi

node.js - 如何使用 nodejs 提供图像

转载 作者:IT老高 更新时间:2023-10-28 21:46:32 25 4
gpt4 key购买 nike

我有一个位于 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');
它有效,但是当我请求 localhost:8080/logo.gif 时那么我显然没有得到这个标志。
我需要做哪些更改才能提供图像。

最佳答案

2016年更新

使用 Express 和不使用 Express 的实际工作示例

这个问题已经超过 5 年了,但 每个回答都有问题 .

TL; 博士

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

  • 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模块是 splinter .他们介绍 比赛条件 , 不安全的路径解析 这将导致 路径遍历漏洞 , 阻塞 I/O 那将完全 无法处理任何并发请求 在所有和其他微妙的问题 - 它们完全被打破作为问题所询问的示例,但它们已经使用了 http 提供的抽象。模块而不是使用 TCP 套接字,因此他们甚至不会像他们声称的那样从头开始做所有事情。

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

    简而言之,问题是如何提供图像,答案是使用适当的模块在 中执行此操作。安全、先进和可靠的方式 可读、可维护和面向 future 使用 时最佳实践 专业 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中间件。提供静态文件是作为使用流的单个路由处理程序实现的。

    此示例具有简单的路径遍历对策并支持一组有限的最常见 MIME 类型。
    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.js 中 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.js 中 TCP 套接字的最低级 API。

    此示例具有 http 的一些功能版本但最小和不完整的 HTTP 协议(protocol)是从头开始实现的。由于它不支持分块编码,因此在发送响应之前将文件加载到内存中以了解大小,因为统计文件然后加载会引入竞争条件。
    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/');
    });

    下载示例

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

    示例与 express.static , express , connect , httpnet :
  • https://github.com/rsp/node-static-http-servers

  • 其他项目仅使用 express.static :
  • https://github.com/rsp/node-express-static-example

  • 测试

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

  • 一切都在 Node 版本 4、5、6 和 7 上进行了测试。

    也可以看看

    其他相关回答:
  • 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
  • Node JS not serving the static image
  • 关于node.js - 如何使用 nodejs 提供图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5823722/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com