nodejs를 사용하여 이미지를 서비스하는 방법
는 가 있습니다.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;DR
아래로 스크롤하여 이미지를 제공하는 예제:
express.staticexpressconnecthttpnet
모든 예는 GitHub에 있습니다. https://github.com/rsp/node-static-http-servers
테스트 결과는 Travis: https://travis-ci.org/rsp/node-static-http-servers 에서 확인할 수 있습니다.
서론
이 질문을 받은 지 5년이 넘었는데 일반적인 헨리에 의한 정답은 하나인데 코드에 문제가 없는데도 수신에 문제가 있는 것 같습니다."다른 사람에게 의존해서 일을 처리하는 방법 외에는 별 설명이 되지 않는다"는 의견이 있었고, 이 의견에 투표한 사람이 몇 명이나 된다는 사실은 많은 것들이 해명이 필요하다는 것을 보여줍니다.
우선 "Node.js를 사용하여 이미지를 서비스하는 방법"에 대한 좋은 답은 정적 파일 서버를 처음부터 구현하지 않고 잘못 수행하는 것입니다.Express와 같은 모듈을 사용하는 것이 좋은 답입니다.
Express를 사용하는 것이 "다른 사람에게 작업을 수행하는 방법 외에 다른 사람에게 의존하는 방법을 설명하지 못한다"는 의견에 답하는 것은 다음을 사용한다는 점에 유의해야 합니다.http모듈은 이미 작업을 완료하기 위해 다른 사람에게 의존하고 있습니다.누군가가 작업을 완료하는 데 다른 사람에게 의존하지 않으려면 최소한 원시 TCP 소켓을 사용해야 합니다. 아래 예 중 하나에서 이 작업을 수행합니다.
더 이 을 입니다.http모듈이 고장났습니다.이들은 경쟁 조건, 경로 횡단 취약성을 초래할 불안정한 경로 해결, 동시 요청을 전혀 처리하지 못할 I/O 차단 및 기타 미묘한 문제들을 소개합니다. 이들은 질문에 대한 예시로서 완전히 깨졌습니다.그럼에도 불구하고 그들은 이미 그들에 의해 제공된 추상화를 사용합니다.httpTCP 소켓을 사용하는 대신 모듈을 사용하기 때문에 그들은 그들의 주장대로 모든 것을 처음부터 하지도 않습니다.
"학습 연습으로서 정적 파일 서버를 처음부터 구현하는 방법"이라는 질문을 받았다면, 그 방법에 대한 답은 반드시 게시되어야 하지만, 그래도 최소한 정확하기를 기대해야 합니다.또한 이미지를 서비스하려는 사용자가 향후 더 많은 이미지를 서비스하고 싶어할 수 있다고 가정하는 것도 무리는 아닙니다. 따라서 하드 코딩된 경로로 단일 파일만 서비스할 수 있는 특정 사용자 지정 정적 파일 서버를 작성하는 것은 다소 근시안적이라고 주장할 수 있습니다.이미지를 서비스하는 방법에 대한 답을 찾는 사람이 어떤 이미지를 서비스하는 일반적인 솔루션이 아닌 하나의 이미지만을 서비스하는 솔루션에 만족할 것이라고 상상하기는 어려울 것 같습니다.
간단히 말해, 이미지를 어떻게 제공할 것인가가 문제이며, 이에 대한 답은 적절한 모듈을 사용하여 전문 노드 개발의 모범 사례를 사용하는 동시에 읽기 쉽고, 유지보수 가능하며, 미래에 대비할 수 있는 안전하고, 성능적이며, 신뢰할 수 있는 방법으로 이미지를 제공하는 것입니다.하지만 그러한 답변에 많은 추가 사항이 있다면 동일한 기능을 수동으로 구현하는 방법을 보여주겠지만 안타깝게도 지금까지 이를 위한 모든 시도가 실패했다는 것에 동의합니다.그것이 제가 몇 가지 새로운 예를 쓴 이유입니다.
이 짧은 소개 후에, 여기 5가지 추상화 수준에 대한 작업을 수행하는 5가지 예가 있습니다.
최소기능
는 합니다.public 및리(디렉토리)합니다의 합니다.
- 대부분의 일반 파일에 대한 MIME 유형
- HTML, JS, CSS, 일반 텍스트 및 이미지를 제공합니다.
- 을 합니다.
index.html - 누락된 파일에 대한 오류 코드로 응답합니다.
- 경로 횡단 취약성 없음
- 파일을 읽는 동안 레이스 조건 없음
노드 버전 4, 5, 6, 7에서 모든 버전을 테스트했습니다.
express.static
이 버전은 모듈의 내장 미들웨어를 사용합니다.
이 예제는 가장 많은 기능과 가장 적은 양의 코드를 가지고 있습니다.
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.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
이 버전은 모듈을 사용합니다. 모듈은 다음보다 낮은 추상화 수준입니다.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
이 버전은 Node에서 HTTP를 위한 가장 낮은 수준의 API인 module을 사용합니다.
는 있습니다.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
이 버전은 Node의 TCP 소켓에 대해 가장 낮은 수준의 API인 모듈을 사용합니다.
에는 의 몇 이 있습니다.http 및 version한 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.static,express,connect,http그리고.net:
만 가능합니다.express.static:
테스트
테스트 결과는 Travis에서 확인할 수 있습니다.
노드 버전 4, 5, 6, 7에서 모든 것이 테스트됩니다.
참고 항목
기타 관련 답변:
- Javascript를 리디렉션할 때 동일한 디렉토리에서 리소스를 로드하지 못했습니다.
- onload js 호출이 노드와 함께 작동하지 않음
- express와 함께 전체 폴더 컨텐츠를 클라이언트에 전송하는 중
- 서버 JS에서 부분 로드가 실패함
- 노드 JS가 정적 이미지를 서비스하지 않습니다.
저는 결국 익스프레스와 같은 틀을 사용해야 한다는 다른 포스터들에 동의합니다.하지만 먼저 도서관 없이 어떻게 이런 근본적인 일을 할 수 있는지, 도서관이 당신을 위해 무엇을 추상하는지 정말로 이해해야 합니다.단계는.
- 수신 HTTP 요청을 구문 분석하여 사용자가 요청하는 경로를 확인합니다.
- 서버가 응답할 경로를 조건문에 추가합니다.
- 이미지가 요청되면 디스크에서 이미지 파일을 읽습니다.
- 머리글에 이미지 내용 형식 제공
- 본문의 이미지 컨텐츠를 위한 서비스
코드는 이와 같습니다(테스트되지 않음).
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');
급행 프레임워크를 이용하셔야 합니다.
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가 작동해야 합니다.
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');
너무 늦었지만 제가 사용하고 있는 사람을 도와줍니다.node version v7.9.0그리고.express 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);
요청에 따른 바닐라 노드 버전:
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');
REST 서비스는 Restify를 이용하는 것을 좋아합니다.저의 경우 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();
}
.js 를(서))를 통해 제공되는 를 벗어난 일 수 .fs.createReadStream('./image/demo.jpg').pipe(res)실제로 좋은 아이디어입니다). 하지만 프로덕션에서는 노드 앱이 다른 방식으로는 해결할 수 없는 작업을 처리하고 정적 서빙을 예를 들어 Nginx로 오프로드하기를 원할 수 있습니다.
이것은 당신의 앱 내부의 코딩이 적음을 의미하며, 역방향 프록시는 이것에 이상적이기 때문에 더 나은 효율성을 의미합니다.
이 방법은 역동적이지 않고 핵심적인 부분을 정확하게 파악할 수 있습니다.
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 );
위의 답변에 덧붙이자면, 웹 트래픽의 90%가 이미지이기 때문에 이미지를 최적화하고 반응형 이미지를 제공하는 것이 페이지 로딩 시간에 큰 도움이 된다는 것입니다.이상적으로 Grunt 또는 Gulp를 사용한 빌드 프로세스 중에 이미지민 및 관련 플러그인과 같은 JS/Node 모듈을 사용하여 이미지를 사전 처리하는 것이 좋습니다.
이미지를 최적화한다는 것은 이상적인 이미지 유형을 찾고, 이미지 품질과 파일 크기의 균형을 맞추기 위해 최적의 압축을 선택하는 것을 의미합니다.
반응형 이미지를 제공하는 것은 각 이미지의 여러 크기와 형식을 자동으로 만들어 사용하는 것을 의미합니다.srcsetHTML에서 모든 브라우저에 대해 최적의 이미지 세트(즉, 이상적인 형식과 치수, 따라서 최적의 파일 크기)를 제공할 수 있습니다.
빌드 프로세스 중의 이미지 처리 자동화는 한 번 통합하고, 이후에 최적화된 이미지를 표시함으로써 최소한의 추가 시간이 필요하다는 것을 의미합니다.
반응형 이미지, 일반적인 미니화, 이미지 미니 노드 모듈 및 srcset 사용에 대한 좋은 읽기.
//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");
});
import http from "node:http";
import fs from "node:fs";
const app = http.createServer((req, res)=>{
if(req.url === "/" && req.method === "GET"){
res.writeHead(200, {
"Content-Type" : "image/jpg"
})
fs.readFile("sending.jpg", (err, data)=>{
if(err){
throw err;
}else{
res.write(data);
res.end();
}
})
}
}).listen(8080, ()=>{
console.log(8080)
})
express는 HTTP/3을 지원합니까?아니.
HTTP/2는 어떻습니까?아니.
나중에 증명이 안 된 것 같아요.
모듈에 의존하는 문제는 표준이 바뀌면 빨리 업데이트되지 않는 문제입니다.충고를 받다.
언급URL : https://stackoverflow.com/questions/5823722/how-to-serve-an-image-using-nodejs
'codememo' 카테고리의 다른 글
| XSL: xsl: template의 match="/"의 의미 (0) | 2023.10.20 |
|---|---|
| lodash에 일치하는 아이템을 대체할 수 있는 기능이 있습니까? (0) | 2023.10.20 |
| 오라클 번호부터 C# 십진수까지 (0) | 2023.10.15 |
| R에서 데이터 프레임과 목록의 차이점은 무엇입니까? (0) | 2023.10.15 |
| Angular ui-router $state.go가 내부 확인으로 리디렉션되지 않습니다. (0) | 2023.10.15 |