J’ai un logo qui réside au public / images / logo.gif. Voici mon code nodejs.
http.createServer(function(req, res){ res.writeHead(200, {'Content-Type': 'text/plain' }); res.end('Hello World \n'); }).listen(8080, '127.0.0.1');
Cela fonctionne mais quand je demande localhost: 8080 / logo.gif alors je n’ai évidemment pas le logo.
Quels changements dois-je apporter pour servir une image?
Je suis d’accord avec les autres affiches que finalement, vous devriez utiliser un framework, tel qu’Express .. mais vous devez d’abord comprendre comment faire quelque chose de fondamental comme celui-ci sans bibliothèque, pour vraiment comprendre ce que la bibliothèque les étapes sont
Le code ressemblerait à ceci (non testé)
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');
Cette question a plus de 5 ans mais chaque réponse pose quelques problèmes .
Faites défiler les exemples pour servir une image avec:
express.static
express
connect
http
net
Tous les exemples sont également sur GitHub: https://github.com/rsp/node-static-http-servers
Les résultats des tests sont disponibles sur Travis: https://travis-ci.org/rsp/node-static-http-servers
Après plus de 5 ans depuis que cette question a été posée, il n’y a qu’une seule réponse correcte par generalhenry, mais même si cette réponse ne pose aucun problème avec le code, elle semble avoir des problèmes de réception . Il a été dit que cela n’expliquait pas grand chose d’autre que la manière de compter sur quelqu’un pour faire le travail et le fait que beaucoup de personnes aient voté ce commentaire montre clairement que beaucoup de choses ont besoin de clarification.
Tout d’abord, une bonne réponse à “Comment servir des images avec Node.js” n’est pas d’implémenter un serveur de fichiers statique à partir de rien et de le faire mal. Une bonne réponse consiste à utiliser un module comme Express qui fait correctement le travail .
Il convient de noter que le fait d’utiliser le module http
dépend déjà de quelqu’un d’autre pour faire le travail. Si quelqu’un ne veut pas faire confiance à qui que ce soit pour faire le travail, alors au moins les sockets TCP bruts doivent être utilisés – ce que je fais dans l’un des exemples ci-dessous.
Un problème plus grave est que toutes les réponses qui utilisent le module http
sont cassées . Ils introduisent des conditions de course , une résolution de chemin non sécurisée qui mènera à une vulnérabilité de parcours , bloquant les E / S qui ne répondront à aucune demande simultanée et d’autres problèmes subtils – ils sont complètement brisés en tant qu’exemples de la question posée et pourtant, ils utilisent déjà l’abstraction fournie par le module http
au lieu d’utiliser les sockets TCP, de sorte qu’ils ne font même pas tout ce qu’ils prétendent.
Si la question était “Comment implémenter un serveur de fichiers statique en partant de zéro, en tant qu’exercice d’apprentissage”, alors répondez par tous les moyens – mais même alors, nous devrions nous attendre à ce qu’ils soient au moins corrects . De plus, il n’est pas déraisonnable de supposer que quelqu’un qui veut servir une image peut vouloir diffuser plus d’images à l’avenir. On peut donc affirmer que l’écriture d’un serveur de fichiers statique spécifique ne pouvant contenir qu’un seul fichier avec un chemin codé est un peu myope. Il semble difficile d’imaginer que quiconque recherche une réponse sur la façon de servir une image se contente d’une solution qui ne sert qu’une seule image au lieu d’une solution générale pour servir une image.
En bref, la question est de savoir comment servir une image et une réponse à cela est d’utiliser un module approprié pour le faire de manière sécurisée, préformée et fiable , lisible, maintenable et pérenne, tout en utilisant les meilleures pratiques des nœuds professionnels. développement. Mais je suis d’accord pour dire qu’un excellent ajout à une telle solution serait de montrer un moyen d’implémenter les mêmes fonctionnalités manuellement, mais malheureusement, toutes les tentatives pour y parvenir ont échoué jusqu’à présent. Et c’est pourquoi j’ai écrit de nouveaux exemples.
Après cette courte introduction, voici mes cinq exemples faisant le travail sur 5 niveaux d’abstraction différents.
Chaque exemple sert des fichiers du répertoire public
et prend en charge la fonctionnalité minimale de:
index.html
comme index de répertoire par défaut J’ai testé chaque version sur les versions Node 4, 5, 6 et 7.
express.static
Cette version utilise le express.static
intégré express.static
du module express
.
Cet exemple a le plus de fonctionnalités et le moins de 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
Cette version utilise le module express
mais sans le middleware express.static
. Servir des fichiers statiques est implémenté en tant que gestionnaire de routage unique à l’aide de stream.
Cet exemple a des contre-mesures de parcours simples et prend en charge un ensemble limité de types MIME les plus courants.
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
Cette version utilise le module de connect
qui est un niveau d’abstraction inférieur à express
.
Cet exemple a des fonctionnalités similaires à la version express
mais utilise des API à levier légèrement inférieur.
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.toSsortingng().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
Cette version utilise le module http
qui est l’API de plus bas niveau pour HTTP dans Node.
Cet exemple a des fonctionnalités similaires à la version de connect
mais utilise encore plus d’API de niveau inférieur.
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.toSsortingng().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
Cette version utilise le module net
qui est l’API de niveau le plus bas pour les sockets TCP dans Node.
Cet exemple présente certaines des fonctionnalités de la version http
, mais le protocole HTTP minimal et incomplet a été implémenté à partir de zéro. Comme il ne prend pas en charge le codage par blocs, il charge les fichiers en mémoire avant de les servir pour connaître la taille avant d’envoyer une réponse, car la mise en attente des fichiers et leur chargement introduiraient une condition de concurrence.
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.toSsortingng().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/'); });
J’ai posté tous les exemples sur GitHub avec plus d’explications.
Exemples avec express.static
, express
, connect
, http
et net
:
Autre projet utilisant uniquement express.static
:
Les résultats des tests sont disponibles sur Travis:
Tout est testé sur les versions de nœud 4, 5, 6 et 7.
Autres réponses connexes:
Vous devez utiliser le cadre express .
npm install express
var express = require('express'); var app = express(); app.use(express.static(__dirname + '/public')); app.listen(8080);
et ensuite l’url localhost: 8080 / images / logo.gif devrait fonctionner
J’aime utiliser Restify pour les services REST. Dans mon cas, j’avais créé un service REST pour servir des images, puis si une source d’image renvoyait 404/403, je voulais renvoyer une autre image. Voici ce que j’ai imaginé en combinant certaines choses ici:
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(); }
Version nœud vanille comme demandé:
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');
Il est trop tard mais aide quelqu’un, j’utilise la node version v7.9.0
et express version 4.15.0
si votre structure de répertoire est quelque chose comme ça:
your-project uploads package.json server.js
code 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);
Vous devez utiliser une bibliothèque compatible avec les URL et les fichiers statiques. Je recommande d’utiliser Express . Il possède des fonctionnalités pour la configuration des routes et un module de service de fichiers statiques.
Tout d’abord, vous devez installer un package express par npm . Vous pouvez l’installer en utilisant npm i express
.
Une fois le module express installé, spécifiez le code suivant dans votre fichier:
const express = require('express'); const app = express(); app.use(express.static('public/images'));
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');