NodeJS में बेसिक स्टैटिक फाइल सर्वर


85

मैं नोड में एक सटीक सर्वर के बजाय नोड को समझने के लिए एक अभ्यास के रूप में एक स्थिर फ़ाइल सर्वर बनाने की कोशिश कर रहा हूं। मैं कनेक्ट और नोड-स्टेटिक जैसी परियोजनाओं से अच्छी तरह से वाकिफ हूं और पूरी तरह से अधिक उत्पादन-तैयार कोड के लिए उन पुस्तकालयों का उपयोग करने का इरादा रखता हूं, लेकिन मैं उन मूल बातों को समझना भी पसंद करता हूं जो मैं काम कर रहा हूं। इसे ध्यान में रखते हुए, मैंने एक छोटे से सर्वर को कोडित किया है। js:

var http = require('http'),
    url = require('url'),
    path = require('path'),
    fs = require('fs');
var mimeTypes = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "png": "image/png",
    "js": "text/javascript",
    "css": "text/css"};

http.createServer(function(req, res) {
    var uri = url.parse(req.url).pathname;
    var filename = path.join(process.cwd(), uri);
    path.exists(filename, function(exists) {
        if(!exists) {
            console.log("not exists: " + filename);
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.write('404 Not Found\n');
            res.end();
        }
        var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
        res.writeHead(200, mimeType);

        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);

    }); //end path.exists
}).listen(1337);

मेरा सवाल दुगना है

  1. क्या नोड में मूल html आदि बनाने और स्ट्रीमिंग करने के बारे में यह "सही" तरीका है या बेहतर / अधिक सुरुचिपूर्ण / अधिक मजबूत विधि है?

  2. मूल रूप से .pipe () मूल रूप से निम्नलिखित कार्य कर रहा है?

var fileStream = fs.createReadStream(filename);
fileStream.on('data', function (data) {
    res.write(data);
});
fileStream.on('end', function() {
    res.end();
});

सबको धन्यवाद!


2
मैंने एक मॉड्यूल लिखा है जो आपको लचीलेपन से समझौता किए बिना ऐसा करने देता है। यह आपके सभी संसाधनों को स्वचालित रूप से कैश कर देता है। इसे देखें: github.com/topcloud/cachemere
Jon

2
HTTP स्थिति कोड OK 200 OK ’के साथ Not 404 Not Found’ को वापस करने के लिए आपके द्वारा चुना गया ()! यदि URL पर कोई संसाधन नहीं पाया जाता है, तो उपयुक्त कोड 404 होना चाहिए (और जो आप दस्तावेज़ में लिखते हैं वह आमतौर पर द्वितीयक महत्व का होता है)। अन्यथा आप बहुत से उपयोगकर्ता एजेंटों (वेब ​​क्रॉलर और अन्य बॉट्स सहित) को भ्रमित कर रहे होंगे, उन्हें बिना किसी वास्तविक मूल्य के दस्तावेज़ दे सकते हैं (जिसमें वे कैश भी हो सकते हैं)।
एमएन

1
धन्यवाद। फिर भी कई साल बाद अच्छी तरह से काम करना।
स्टेटोसेडॉटकॉम

1
धन्यवाद! यह कोड पूरी तरह से काम कर रहा है। लेकिन अब उपरोक्त कोड के fs.exists()बजाय उपयोग करें path.exists()। चीयर्स! और हाँ! मत भूलो return:
कौशल्या ३

नोट : 1) fs.exists() है पदावनतfs.access()उपर्युक्त उपयोग के मामले के लिए उपयोग या उससे भी बेहतर fs.stat()2) url.parse है पदावनत ; new URLइसके बजाय नए इंटरफ़ेस का उपयोग करें।
rags2riches

जवाबों:


44
  • आपके मूल सर्वर को छोड़कर अच्छा लगता है:

    एक returnबयान गायब है।

    res.write('404 Not Found\n');
    res.end();
    return; // <- Don't forget to return here !!
    

    तथा:

    res.writeHead(200, mimeType);

    होना चाहिए:

    res.writeHead(200, {'Content-Type':mimeType});

  • हां pipe()मूल रूप से ऐसा करता है, यह स्रोत धारा को रोक देता है / फिर से शुरू करता है (यदि रिसीवर धीमा है)। यहाँ pipe()समारोह का स्रोत कोड है : https://github.com/joyent/node/blob/master/lib/n.s


2
यदि फ़ाइल का नाम blah.blah.css जैसा है तो क्या होगा?
ShrekOverflow

2
mimeType उस मामले में blah होगा xP
ShrekOverflow

5
कि रगड़ हालांकि नहीं है? यदि आप अपना स्वयं का लिखते हैं, तो आप इस प्रकार के कीड़े के लिए पूछ रहे हैं। अच्छा सीखना अंश है लेकिन मैं अपने रोल को करने के बजाय "कनेक्ट" की सराहना करना सीख रहा हूं। इस पृष्ठ के साथ समस्या यह है कि लोग केवल यह जानने के लिए देख रहे हैं कि एक साधारण फ़ाइल सर्वर कैसे करें और स्टैक ओवरफ्लो सबसे पहले आता है। यह उत्तर सही है लेकिन लोग इसके लिए सरल उत्तर नहीं खोज रहे हैं। मुझे खुद को सरल पता लगाना था इसलिए इसे यहाँ रखा।
जेसन सेब्रिंग

1
लाइब्रेरी के रूप में समाधान के लिंक को चिपकाने के लिए नहीं बल्कि वास्तव में प्रश्न का उत्तर लिखने के लिए +1।
शॉन व्हेनरी

57

थोड़ा ही काफी है

बस अपनी परियोजना और उपयोग पर सबसे पहले कमांड प्रॉम्प्ट पर जाएं

$ npm install express

फिर अपना app.js कोड इस तरह लिखें:

var express = require('express'),
app = express(),
port = process.env.PORT || 4000;

app.use(express.static(__dirname + '/public'));
app.listen(port);

आप तब एक "सार्वजनिक" फ़ोल्डर बनाएंगे, जहाँ आप अपनी फाइलें रखेंगे। मैंने इसे पहले कठिन तरीके से आजमाया था, लेकिन आपको माइम के प्रकारों के बारे में चिंता करनी होगी जो कि केवल सामान को मैप करने के लिए है जो समय लेने वाली है और फिर प्रतिक्रिया प्रकार, आदि आदि के बारे में चिंता करें .... धन्यवाद नहीं।


2
+1 अपने स्वयं के रोल करने के बजाय परीक्षण किए गए कोड का उपयोग करने के लिए बहुत कुछ कहा जा सकता है।
जूलम

1
मैंने दस्तावेज़ीकरण को देखने की कोशिश की, लेकिन बहुत कुछ नहीं मिल रहा है, क्या आप बता सकते हैं कि आपका स्निपेट क्या कर रहा है? मैंने इस विशेष भिन्नता का उपयोग करने की कोशिश की और मुझे नहीं पता कि क्या बदला जा सकता है।
onaclov2000

3
यदि आप निर्देशिका लिस्टिंग चाहते हैं, तो बस कनेक्ट .static लाइन के बाद, .use (connect.directory ('सार्वजनिक')) जोड़ दें, अपने स्थान के साथ, सार्वजनिक प्रतिस्थापित करें। अपहरण के लिए खेद है, लेकिन मुझे लगता है कि यह मेरे लिए चीजों को साफ करता है।
onaclov2000

1
आप 'उपयोग jQuery' भी कर सकते हैं! यह ओपी के सवाल का एक पहलू नहीं है, बल्कि एक समस्या का समाधान है जो मौजूद नहीं है। ओपी ने कहा कि इस प्रयोग का उद्देश्य नोड सीखना था।
शॉन व्हेनरी

1
@JasonSebring require('http')दूसरी पंक्ति में क्यों ?
जिओ पेंग - ZenUML.com

19

मुझे यह समझना पसंद है कि हुड के तहत क्या हो रहा है।

मैंने आपके कोड में कुछ चीजों पर ध्यान दिया है जिन्हें आप शायद साफ करना चाहते हैं:

  • जब फ़ाइलनाम किसी निर्देशिका की ओर इंगित करता है, तो यह क्रैश हो जाता है, क्योंकि मौजूद सत्य है और यह एक फ़ाइल स्ट्रीम पढ़ने की कोशिश करता है। निर्देशिका अस्तित्व का निर्धारण करने के लिए मैंने fs.lstatSync का उपयोग किया।

  • यह HTTP प्रतिक्रिया कोड का सही (200, 404, आदि) का उपयोग नहीं कर रहा है

  • जबकि MimeType का निर्धारण किया जा रहा है (फ़ाइल एक्सटेंशन से), इसे res.writeHead में सही तरीके से सेट नहीं किया जा रहा है (जैसा कि बाहर बताया गया है)

  • विशेष वर्णों को संभालने के लिए, आप संभवत: यूआरआई को हटाना चाहते हैं

  • यह नेत्रहीन रूप से सीमलिंक का अनुसरण करता है (सुरक्षा चिंता का विषय हो सकता है)

इसे देखते हुए, कुछ अपाचे विकल्प (FollowSymLinks, ShowIndexes, आदि) अधिक समझ में आने लगते हैं। मैंने आपके सरल फ़ाइल सर्वर के लिए कोड को निम्नानुसार अपडेट किया है:

var http = require('http'),
    url = require('url'),
    path = require('path'),
    fs = require('fs');
var mimeTypes = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "png": "image/png",
    "js": "text/javascript",
    "css": "text/css"};

http.createServer(function(req, res) {
  var uri = url.parse(req.url).pathname;
  var filename = path.join(process.cwd(), unescape(uri));
  var stats;

  try {
    stats = fs.lstatSync(filename); // throws if path doesn't exist
  } catch (e) {
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.write('404 Not Found\n');
    res.end();
    return;
  }


  if (stats.isFile()) {
    // path exists, is a file
    var mimeType = mimeTypes[path.extname(filename).split(".").reverse()[0]];
    res.writeHead(200, {'Content-Type': mimeType} );

    var fileStream = fs.createReadStream(filename);
    fileStream.pipe(res);
  } else if (stats.isDirectory()) {
    // path exists, is a directory
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('Index of '+uri+'\n');
    res.write('TODO, show index?\n');
    res.end();
  } else {
    // Symbolic link, other?
    // TODO: follow symlinks?  security?
    res.writeHead(500, {'Content-Type': 'text/plain'});
    res.write('500 Internal server error\n');
    res.end();
  }

}).listen(1337);

4
क्या मैं "var mimeType = mimeTypes [path.extname (फ़ाइल नाम) .sitit (" "।") को उल्टा () [0]]; बजाय? कुछ फ़ाइलनाम में एक से अधिक "हैं।" उदाहरण के लिए "my.cool.video.mp4" या "download.tar.gz"
अनसिंक्रनाइज़्ड

क्या यह किसी तरह फ़ोल्डर /../../../ के उपयोग से किसी को रोक देता है / घर / उपयोगकर्ता / जैकपॉट। मुझे लगता है कि मार्ग नीचे की ओर सुनिश्चित करने के लिए जुड़ता है, लेकिन मैं सोच रहा हूं कि क्या ../../..// का उपयोग करते हुए संकेतन उस के आसपास मिलेगा या नहीं। शायद मैं खुद इसका परीक्षण करूंगा।
रेनार्ड

यह काम नहीं करता। मुझे यकीन नहीं है कि क्यों, लेकिन यह जानना अच्छा है।
रेनार्ड

अच्छा, एक RegEx मैच भी एक्सटेंशन इकट्ठा कर सकता है; var mimeType = mimeTypes[path.extname(filename).match(/\.([^\.]+)$/)[1]];
जॉन मटुमा

4
var http = require('http')
var fs = require('fs')

var server = http.createServer(function (req, res) {
  res.writeHead(200, { 'content-type': 'text/plain' })

  fs.createReadStream(process.argv[3]).pipe(res)
})

server.listen(Number(process.argv[2]))

4
शायद इसे थोड़ा और समझाना चाहते हैं।
नाथन तुग्गी

3

इस पैटर्न के बारे में कैसे, जो अलग से जाँचने से बचता है कि फ़ाइल मौजूद है

        var fileStream = fs.createReadStream(filename);
        fileStream.on('error', function (error) {
            response.writeHead(404, { "Content-Type": "text/plain"});
            response.end("file not found");
        });
        fileStream.on('open', function() {
            var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
            response.writeHead(200, {'Content-Type': mimeType});
        });
        fileStream.on('end', function() {
            console.log('sent file ' + filename);
        });
        fileStream.pipe(response);

1
सफलता के मामले में आप भूल गए। मैं इस डिज़ाइन का उपयोग कर रहा हूं, लेकिन तुरंत धाराओं को पाइप करने के बजाय, मैं उन्हें फिल्मस्ट्रीम के 'ओपन' इवेंट में पाइप कर रहा हूं: राइटहेड फॉर द मीमाइप, फिर पाइप। समाप्ति की आवश्यकता नहीं है: readable.pipe
GeH

@GeH की टिप्पणी के अनुसार संशोधित।
ब्रेट ज़मीर

होना चाहिएfileStream.on('open', ...
पेटा

2

मैंने @ जेफ़ वार्ड जवाब के आधार पर सामान्य उपयोग के लिए अतिरिक्त सुविधाओं के साथ एक httpServer फ़ंक्शन बनाया

  1. custtom dir
  2. index.html रिटर्न अगर === dir है

उपयोग:

httpServer(dir).listen(port);

https://github.com/kenokabe/ConciseStaticHttpServer

धन्यवाद।


0

सेंट मॉड्यूल स्टैटिक फ़ाइलें आसान की सेवा करता है। यहाँ README.md का एक उद्धरण है:

var mount = st({ path: __dirname + '/static', url: '/static' })
http.createServer(function(req, res) {
  var stHandled = mount(req, res);
  if (stHandled)
    return
  else
    res.end('this is not a static file')
}).listen(1338)

0

@JasonSebring उत्तर ने मुझे सही दिशा में बताया, हालाँकि उनका कोड पुराना है। यहाँ है कि आप इसे नवीनतम connectसंस्करण के साथ कैसे करते हैं ।

var connect = require('connect'),
    serveStatic = require('serve-static'),
    serveIndex = require('serve-index');

var app = connect()
    .use(serveStatic('public'))
    .use(serveIndex('public', {'icons': true, 'view': 'details'}))
    .listen(3000);

में connect GitHub भंडार अन्य middlewares आप उपयोग कर सकते हैं।


मैंने सिर्फ एक सरल उत्तर के लिए एक्सप्रेस का इस्तेमाल किया। नवीनतम एक्सप्रेस संस्करण में स्थिर बेक्ड है, लेकिन बहुत अधिक नहीं। धन्यवाद!
जेसन सेब्रिंग

connectप्रलेखन को देखते हुए , यह केवल एक के wrapperलिए है middleware। सभी अन्य रोचक middlewareसे हैं expressतो तकनीकी रूप से आप उन का उपयोग कर एपीआई इस्तेमाल कर सकते हैं भंडार, express.use()
फ्लीफएंड्रो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.