如何使用 Node.js 提供图像

发布于 2024-11-04 03:17:27 字数 322 浏览 1 评论 0原文

我的徽标位于 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 时,我显然没有得到徽标。

我需要做哪些改变才能提供图像。

I have a logo that is residing at the public/images/logo.gif. Here is my nodejs code.

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

It works but when I request for localhost:8080/logo.gif then I obviously don't get the logo.

What changes I need to do to serve an image.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

寒冷纷飞旳雪 2024-11-11 03:17:27

2016 年更新

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

这个问题已有 5 年多了,但每个答案都有一些问题

TL;DR

向下滚动查看使用以下方式提供图像的示例:

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

所有示例也位于 GitHub 上:https://github.com /rsp/node-static-http-servers

测试结果可在特拉维斯: https://travis-ci.org/rsp/node-static-http -servers

简介

自从提出这个问题以来已经过去 5 年多了,只有一个正确答案< /a> 通过generalhenry 但即使该答案对代码没有问题,它似乎在接收方面存在一些问题。有人评论说,它“除了如何依靠别人来完成工作之外,没有解释太多”,而有多少人投票赞成这一评论的事实清楚地表明,很多事情需要澄清。

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

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

更严重的问题是,这里所有使用 http 模块的答案都损坏。它们引入了竞争条件不安全的路径解析(这将导致路径遍历漏洞)、阻塞 I/O(这将导致路径遍历漏洞)完全无法服务任何并发请求以及其他微妙的问题 - 它们作为问题所询问内容的示例完全被破坏,但它们已经使用了 http 提供的抽象 模块而不是使用 TCP 套接字,因此它们甚至不像他们声称的那样一切都从头开始。

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

简而言之,问题是如何提供图像,答案是使用适当的模块以安全、高性能和可靠的方式来实现这一点,即可读、可维护且面向未来- 证明,同时使用专业节点开发的最佳实践。但我同意,对这样的答案的一个很好的补充是展示一种手动实现相同功能的方法,但遗憾的是到目前为止,每一次尝试都失败了。这就是我写一些新例子的原因。

在简短的介绍之后,下面是我在 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 协议。由于它不支持分块编码,因此在发送响应之前将文件加载到内存中以了解文件的大小,因为先统计文件然后加载会引入竞争条件。

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.staticexpressconnecthttpnet 的示例:

  • < a href="https://github.com/rsp/node-static-http-servers" rel="noreferrer">https://github.com/rsp/node-static-http-servers

其他仅使用 express.static 的项目:

测试

测试结果可在 Travis 上获取:

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

另请参阅

其他相关答案:

2016 Update

Examples with Express and without Express that actually work

This question is over 5 years old but every answer has some problems.

TL;DR

Scroll down for examples to serve an image with:

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

All of the examples are also on GitHub: https://github.com/rsp/node-static-http-servers

Test results are available on Travis: https://travis-ci.org/rsp/node-static-http-servers

Introduction

After over 5 years since this question was asked there is only one correct answer by generalhenry but even though that answer has no problems with the code, it seems to have some problems with reception. It was commented that it "doesn't explain much other than how to rely on someone else to get the job done" and the fact how many people have voted this comment up clearly shows that a lot of things need clarification.

First of all, a good answer to "How to serve images using Node.js" is not implementing a static file server from scratch and doing it badly. A good answer is using a module like Express that does the job correctly.

Answering comments that say that using Express "doesn't explain much other than how to rely on someone else to get the job done" it should be noted, that using the http module already relies on someone else to get the job done. If someone doesn't want to rely on anyone to get the job done then at least raw TCP sockets should be used instead - which I do in one of my examples below.

A more serious problem is that all of the answers here that use the http module are broken. They introduce race conditions, insecure path resolution that will lead to path traversal vulnerability, blocking I/O that will completely fail to serve any concurrent requests at all and other subtle problems - they are completely broken as examples of what the question asks about, and yet they already use the abstraction that is provided by the http module instead of using TCP sockets so they don't even do everything from scratch as they claim.

If the question was "How to implement static file server from scratch, as a learning exercise" then by all means answers how to do that should be posted - but even then we should expect them to at least be correct. Also, it is not unreasonable to assume that someone who wants to serve an image might want to serve more images in the future so one could argue that writing a specific custom static file server that can serve only one single file with hard-coded path is somewhat shortsighted. It seems hard to imagine that anyone who searches for an answer on how to serve an image would be content with a solution that serves just a single image instead of a general solution to serve any image.

In short, the question is how to serve an image and an answer to that is to use an appropriate module to do that in a secure, performant and reliable way that is readable, maintainable and future-proof while using the best practice of professional Node development. But I agree that a great addition to such an answer would be showing a way to implement the same functionality manually but sadly every attempt to do that has failed so far. And that is why I wrote some new examples.

After this short introduction, here are my five examples doing the job on 5 different levels of abstraction.

Minimum functionality

Every example serves files from the public directory and supports the minimum functionality of:

  • MIME types for most common files
  • serves HTML, JS, CSS, plain text and images
  • serves index.html as a default directory index
  • responds with error codes for missing files
  • no path traversal vulnerabilities
  • no race conditions while reading files

I tested every version on Node versions 4, 5, 6 and 7.

express.static

This version uses the express.static built-in middleware of the express module.

This example has the most functionality and the least amount of code.

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

This version uses the express module but without the express.static middleware. Serving static files is implemented as a single route handler using streams.

This example has simple path traversal countermeasures and supports a limited set of most common MIME types.

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

This version uses the connect module which is a one level of abstraction lower than express.

This example has similar functionality to the express version but using slightly lower-lever APIs.

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

This version uses the http module which is the lowest-level API for HTTP in Node.

This example has similar functionality to the connect version but using even more lower-level APIs.

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

This version uses the net module which is the lowest-level API for TCP sockets in Node.

This example has some of the functionality of the http version but the minimal and incomplete HTTP protocol has been implemented from scratch. Since it doesn't support chunked encoding it loads the files into memory before serving them to know the size before sending a response because statting the files and then loading would introduce a race condition.

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/');
});

Download examples

I posted all of the examples on GitHub with more explanation.

Examples with express.static, express, connect, http and net:

Other project using only express.static:

Tests

Test results are available on Travis:

Everything is tested on Node versions 4, 5, 6, and 7.

See also

Other related answers:

⒈起吃苦の倖褔 2024-11-11 03:17:27

我同意其他海报的观点,最终,你应该使用一个框架,例如 Express.. 但首先你还应该了解如何在没有库的情况下做一些基本的事情,以真正理解库为你抽象的内容..步骤是

  1. 解析传入的 HTTP 请求,查看用户请求的路径
  2. 在条件语句中添加一条路径,以便服务器响应
  3. 如果请求图像,则从磁盘读取图像文件。
  4. 在标题中提供图像内容类型 在
  5. 正文中提供图像内容

代码看起来像这样(未经测试)

fs = require('fs');
http = require('http');
url = require('url');


http.createServer(function(req, res){
  var request = url.parse(req.url, true);
  var action = request.pathname;

  if (action == '/logo.gif') {
     var img = fs.readFileSync('./logo.gif');
     res.writeHead(200, {'Content-Type': 'image/gif' });
     res.end(img, 'binary');
  } else { 
     res.writeHead(200, {'Content-Type': 'text/plain' });
     res.end('Hello World \n');
  }
}).listen(8080, '127.0.0.1');

I agree with the other posters that eventually, you should use a framework, such as Express.. but first you should also understand how to do something fundamental like this without a library, to really understand what the library abstracts away for you.. The steps are

  1. Parse the incoming HTTP request, to see which path the user is asking for
  2. Add a pathway in conditional statement for the server to respond to
  3. If the image is requested, read the image file from the disk.
  4. Serve the image content-type in a header
  5. Serve the image contents in the body

The code would look something like this (not tested)

fs = require('fs');
http = require('http');
url = require('url');


http.createServer(function(req, res){
  var request = url.parse(req.url, true);
  var action = request.pathname;

  if (action == '/logo.gif') {
     var img = fs.readFileSync('./logo.gif');
     res.writeHead(200, {'Content-Type': 'image/gif' });
     res.end(img, 'binary');
  } else { 
     res.writeHead(200, {'Content-Type': 'text/plain' });
     res.end('Hello World \n');
  }
}).listen(8080, '127.0.0.1');
清风夜微凉 2024-11-11 03:17:27

您应该使用 express 框架。

npm install express

然后

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080);

URL localhost:8080/images/logo.gif 应该可以工作。

You should use the express framework.

npm install express

and then

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080);

and then the URL localhost:8080/images/logo.gif should work.

禾厶谷欠 2024-11-11 03:17:27
var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
  res.writeHead(200,{'content-type':'image/jpg'});
  fs.createReadStream('./image/demo.jpg').pipe(res);
}).listen(3000);
console.log('server running at 3000');
var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
  res.writeHead(200,{'content-type':'image/jpg'});
  fs.createReadStream('./image/demo.jpg').pipe(res);
}).listen(3000);
console.log('server running at 3000');
柠北森屋 2024-11-11 03:17:27

为时已晚,但对某人有帮助,

如果您的目录结构如下所示,我正在使用 node version v7.9.0express version 4.15.0

your-project
   uploads
   package.json
   server.js

server.js 代码:

var express         = require('express');
var app             = express();
app.use(express.static(__dirname + '/uploads'));// you can access image 
 //using this url: http://localhost:7000/abc.jpg
//make sure `abc.jpg` is present in `uploads` dir.

//Or you can change the directory for hiding real directory name:

`app.use('/images', express.static(__dirname+'/uploads/'));// you can access image using this url: http://localhost:7000/images/abc.jpg


app.listen(7000);

It is too late but helps someone, I'm using node version v7.9.0 and express version 4.15.0

if your directory structure is something like this:

your-project
   uploads
   package.json
   server.js

server.js code:

var express         = require('express');
var app             = express();
app.use(express.static(__dirname + '/uploads'));// you can access image 
 //using this url: http://localhost:7000/abc.jpg
//make sure `abc.jpg` is present in `uploads` dir.

//Or you can change the directory for hiding real directory name:

`app.use('/images', express.static(__dirname+'/uploads/'));// you can access image using this url: http://localhost:7000/images/abc.jpg


app.listen(7000);
黎夕旧梦 2024-11-11 03:17:27

根据要求的香草节点版本:

var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');

http.createServer(function(req, res) {
  // parse url
  var request = url.parse(req.url, true);
  var action = request.pathname;
  // disallow non get requests
  if (req.method !== 'GET') {
    res.writeHead(405, {'Content-Type': 'text/plain' });
    res.end('405 Method Not Allowed');
    return;
  }
  // routes
  if (action === '/') {
    res.writeHead(200, {'Content-Type': 'text/plain' });
    res.end('Hello World \n');
    return;
  }
  // static (note not safe, use a module for anything serious)
  var filePath = path.join(__dirname, action).split('%20').join(' ');
  fs.exists(filePath, function (exists) {
    if (!exists) {
       // 404 missing files
       res.writeHead(404, {'Content-Type': 'text/plain' });
       res.end('404 Not Found');
       return;
    }
    // set the content type
    var ext = path.extname(action);
    var contentType = 'text/plain';
    if (ext === '.gif') {
       contentType = 'image/gif'
    }
    res.writeHead(200, {'Content-Type': contentType });
    // stream the file
    fs.createReadStream(filePath, 'utf-8').pipe(res);
  });
}).listen(8080, '127.0.0.1');

Vanilla node version as requested:

var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');

http.createServer(function(req, res) {
  // parse url
  var request = url.parse(req.url, true);
  var action = request.pathname;
  // disallow non get requests
  if (req.method !== 'GET') {
    res.writeHead(405, {'Content-Type': 'text/plain' });
    res.end('405 Method Not Allowed');
    return;
  }
  // routes
  if (action === '/') {
    res.writeHead(200, {'Content-Type': 'text/plain' });
    res.end('Hello World \n');
    return;
  }
  // static (note not safe, use a module for anything serious)
  var filePath = path.join(__dirname, action).split('%20').join(' ');
  fs.exists(filePath, function (exists) {
    if (!exists) {
       // 404 missing files
       res.writeHead(404, {'Content-Type': 'text/plain' });
       res.end('404 Not Found');
       return;
    }
    // set the content type
    var ext = path.extname(action);
    var contentType = 'text/plain';
    if (ext === '.gif') {
       contentType = 'image/gif'
    }
    res.writeHead(200, {'Content-Type': contentType });
    // stream the file
    fs.createReadStream(filePath, 'utf-8').pipe(res);
  });
}).listen(8080, '127.0.0.1');
忆梦 2024-11-11 03:17:27

我喜欢使用 Restify 来实现 REST 服务。就我而言,我创建了一个 REST 服务来提供图像,然后如果图像源返回 404/403,我想返回替代图像。这是我结合这里的一些内容想到的:

function processRequest(req, res, next, url) {
    var httpOptions = {
        hostname: host,
        path: url,
        port: port,
        method: 'GET'
    };

    var reqGet = http.request(httpOptions, function (response) {
        var statusCode = response.statusCode;

        // Many images come back as 404/403 so check explicitly
        if (statusCode === 404 || statusCode === 403) {
            // Send default image if error
            var file = 'img/user.png';
            fs.stat(file, function (err, stat) {
                var img = fs.readFileSync(file);
                res.contentType = 'image/png';
                res.contentLength = stat.size;
                res.end(img, 'binary');
            });

        } else {
            var idx = 0;
            var len = parseInt(response.header("Content-Length"));
            var body = new Buffer(len);

            response.setEncoding('binary');

            response.on('data', function (chunk) {
                body.write(chunk, idx, "binary");
                idx += chunk.length;
            });

            response.on('end', function () {
                res.contentType = 'image/jpg';
                res.send(body);
            });

        }
    });

    reqGet.on('error', function (e) {
        // Send default image if error
        var file = 'img/user.png';
        fs.stat(file, function (err, stat) {
            var img = fs.readFileSync(file);
            res.contentType = 'image/png';
            res.contentLength = stat.size;
            res.end(img, 'binary');
        });
    });

    reqGet.end();

    return next();
}

I like using Restify for REST services. In my case, I had created a REST service to serve up images and then if an image source returned 404/403, I wanted to return an alternative image. Here's what I came up with combining some of the stuff here:

function processRequest(req, res, next, url) {
    var httpOptions = {
        hostname: host,
        path: url,
        port: port,
        method: 'GET'
    };

    var reqGet = http.request(httpOptions, function (response) {
        var statusCode = response.statusCode;

        // Many images come back as 404/403 so check explicitly
        if (statusCode === 404 || statusCode === 403) {
            // Send default image if error
            var file = 'img/user.png';
            fs.stat(file, function (err, stat) {
                var img = fs.readFileSync(file);
                res.contentType = 'image/png';
                res.contentLength = stat.size;
                res.end(img, 'binary');
            });

        } else {
            var idx = 0;
            var len = parseInt(response.header("Content-Length"));
            var body = new Buffer(len);

            response.setEncoding('binary');

            response.on('data', function (chunk) {
                body.write(chunk, idx, "binary");
                idx += chunk.length;
            });

            response.on('end', function () {
                res.contentType = 'image/jpg';
                res.send(body);
            });

        }
    });

    reqGet.on('error', function (e) {
        // Send default image if error
        var file = 'img/user.png';
        fs.stat(file, function (err, stat) {
            var img = fs.readFileSync(file);
            res.contentType = 'image/png';
            res.contentLength = stat.size;
            res.end(img, 'binary');
        });
    });

    reqGet.end();

    return next();
}
梅倚清风 2024-11-11 03:17:27

这可能有点偏离主题,因为您具体询问的是通过 Node.js 提供静态文件(其中 fs.createReadStream('./image/demo.jpg').pipe(res)实际上是一个好主意),但在生产中,您可能希望让 Node 应用程序处理无法以其他方式处理的任务,并将静态服务卸载到 Nginx 等。

这意味着应用程序内部的编码更少,效率更高,因为反向代理在设计上就是理想的选择。

This may be a bit off-topic, since you are asking about static file serving via Node.js specifically (where fs.createReadStream('./image/demo.jpg').pipe(res) is actually a good idea), but in production you may want to have your Node app handle tasks, that cannot be tackled otherwise, and off-load static serving to e.g Nginx.

This means less coding inside your app, and better efficiency since reverse proxies are by design ideal for this.

月牙弯弯 2024-11-11 03:17:27

这种方法对我有用,它不是动态的,而是开门见山:

const fs      = require('fs');
const express = require('express');
const app     = express();

app.get( '/logo.gif', function( req, res ) {

  fs.readFile( 'logo.gif', function( err, data ) {

    if ( err ) {

      console.log( err );
      return;
    }

    res.write( data );
    return res.end();
  });

});

app.listen( 80 );

This method works for me, it's not dynamic but straight to the point:

const fs      = require('fs');
const express = require('express');
const app     = express();

app.get( '/logo.gif', function( req, res ) {

  fs.readFile( 'logo.gif', function( err, data ) {

    if ( err ) {

      console.log( err );
      return;
    }

    res.write( data );
    return res.end();
  });

});

app.listen( 80 );
萌面超妹 2024-11-11 03:17:27

让我对上面的答案进行补充,优化图像和提供响应式图像可以显着缩短页面加载时间,因为超过 90% 的网络流量都是图像。您可能想要使用 JS / Node 模块预处理图像,例如 imagemin 和相关插件,最好是在使用 Grunt 或 Gulp 的构建过程中。

优化图像是指寻找理想的图像类型,并选择最佳的压缩方式以实现图像质量和文件大小之间的平衡。

提供响应式图像意味着自动为每个图像创建多种尺寸和格式,并在 HTML 中使用 srcset 允许您提供最佳图像集(即理想的格式和尺寸) ,从而为每个浏览器提供最佳文件大小)。

构建过程中的图像处理自动化意味着将其合并一次,然后进一步呈现优化的图像,所需的额外时间最少。

关于响应式图片的一些精彩读物,缩小 一般来说,imagemin 节点模块和 使用 srcset

Let me just add to the answers above, that optimizing images, and serving responsive images helps page loading times dramatically since >90% of web traffic are images. You might want to pre-process images using JS / Node modules such as imagemin and related plug-ins, ideally during the build process with Grunt or Gulp.

Optimizing images means processing finding an ideal image type, and selecting optimal compression to achieve a balance between image quality and file size.

Serving responsive images translates into creating several sizes and formats of each image automatically and using srcset in your HTML allows you to serve optimal image set (that is, the ideal format and dimensions, thus optimal file size) for every single browser).

Image processing automation during the build process means incorporating it up once, and presenting optimized images further on, requiring minimum extra time.

Some great read on responsive images, minification in general, imagemin node module and using srcset.

黑凤梨 2024-11-11 03:17:27
//This method involves directly integrating HTML Code in the res.write
//first time posting to stack ...pls be kind

const express = require('express');
const app = express();
const https = require('https');

app.get("/",function(res,res){
    res.write("<img src="+image url / src +">");
    res.send();
});

app.listen(3000, function(req, res) {
  console.log("the server is onnnn");
});

//This method involves directly integrating HTML Code in the res.write
//first time posting to stack ...pls be kind

const express = require('express');
const app = express();
const https = require('https');

app.get("/",function(res,res){
    res.write("<img src="+image url / src +">");
    res.send();
});

app.listen(3000, function(req, res) {
  console.log("the server is onnnn");
});

我恋#小黄人 2024-11-11 03:17:27

Express 支持 HTTP/3 吗?没有。

HTTP/2 怎么样?没有。

我想未来的证明没有成功。

当标准发生变化时,依赖的模块不能快速更新的问题。请注意。

Does express support HTTP/3? Nope.

How about HTTP/2? Nope.

I guess future proof didn't work out.

The problem of depending on a module that isn't updated quickly when standards change. Be advised.

暗喜 2024-11-11 03:17:27
import http from "node:http";
import fs from "node:fs";

http.createServer((req, res)=>{
    if(req.url === "/" && req.method === "GET"){
        res.writeHead(200, {
            "Content-Type" : "image/jpg"
        })
        fs.readFile("someimage.jpg", (err, data)=>{
            if(err){
                throw err;
            }
             res.write(data);
             res.end();
        })
    }
}).listen(8080);
import http from "node:http";
import fs from "node:fs";

http.createServer((req, res)=>{
    if(req.url === "/" && req.method === "GET"){
        res.writeHead(200, {
            "Content-Type" : "image/jpg"
        })
        fs.readFile("someimage.jpg", (err, data)=>{
            if(err){
                throw err;
            }
             res.write(data);
             res.end();
        })
    }
}).listen(8080);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文