নোডজেএসে বেসিক স্ট্যাটিক ফাইল সার্ভার


85

আমি একটি নিখুঁত সার্ভার হিসাবে নোড বুঝতে অনুশীলন হিসাবে নোডজে একটি স্ট্যাটিক ফাইল সার্ভার তৈরি করার চেষ্টা করছি। আমি কানেক্ট এবং নোড-স্ট্যাটিকের মতো প্রকল্পগুলি সম্পর্কে ভালভাবে সচেতন এবং আরও বেশি উত্পাদন-প্রস্তুত কোডের জন্য এই লাইব্রেরিগুলি ব্যবহার করার সম্পূর্ণ ইচ্ছা করি তবে আমি কী নিয়ে কাজ করছি তার মূল বিষয়গুলিও বুঝতে আগ্রহী। এই বিষয়টি মনে রেখে, আমি একটি ছোট সার্ভার.কোড আপ করেছি।

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. নোডে বেসিক এইচটিএমএল ইত্যাদি তৈরি এবং স্ট্রিমিংয়ের বিষয়ে এটিই কি "সঠিক" উপায় বা আরও ভাল / আরও মার্জিত / আরও শক্তিশালী পদ্ধতি আছে?

  2. নোডে। পাইপ () মূলত কেবল নিম্নলিখিতটিই করছে?

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

ধন্যবাদ সবাইকে!


4
আমি একটি মডিউল লিখেছিলাম যা আপনাকে নমনীয়তা সংযোজন না করে এটি করতে দেয়। এটি স্বয়ংক্রিয়ভাবে আপনার সমস্ত সংস্থানকে ক্যাশে করে। এটি দেখুন: github.com/topcloud/cachemere
জন

4
কিছুটা মজার যে আপনি HTTP স্থিতি কোড '200 ওকে' দিয়ে '404 পাওয়া যায়নি' ফেরত দেওয়ার জন্য (?) চয়ন করেছেন। যদি ইউআরএল-তে কোনও সন্ধানের সন্ধান পাওয়া যায় না, তবে উপযুক্ত কোডটি 404 হওয়া উচিত (এবং আপনি নথির বডিতে যা লেখেন তা সাধারণত গৌণ গুরুত্বের বিষয়)। অন্যথায় আপনি প্রচুর ব্যবহারকারী এজেন্টকে বিভ্রান্ত করবেন (ওয়েব ক্রলার এবং অন্যান্য বট সহ) তাদের কোনও আসল মূল্য ছাড়াই ডকুমেন্টগুলি প্রদান করবেন (যা তারা ক্যাশেও করতে পারে)।
amn

4
ধন্যবাদ এখনও অনেক বছর পরে দুর্দান্ত কাজ।
স্ট্যাটোসডটকম

4
ধন্যবাদ! এই কোড নিখুঁতভাবে কাজ করছে। তবে এখন উপরের কোডের fs.exists()পরিবর্তে ব্যবহার করুন path.exists()। চিয়ার্স! ও হ্যা! ভুলে যাবেন না return:
কাউশাল 28

দ্রষ্টব্য : 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/stream.js


4
ফাইলের নাম blah.blah.css এর মতো হলে কী হবে?
শ্রেকওভারফ্লো


4
যদিও ঘষা নেই? আপনি যদি নিজের লেখেন, আপনি এই ধরণের বাগের জন্য জিজ্ঞাসা করছেন। ভাল শেখার অংশবিশেষ তবে আমি নিজের ঘূর্ণায়মান না হয়ে "সংযুক্ত" প্রশংসা করতে শিখছি। এই পৃষ্ঠাটির সমস্যাটি হ'ল লোকেরা কীভাবে একটি সরল ফাইল সার্ভার করবেন এবং সন্ধানের ওভারফ্লো প্রথম দিকে আসে তা সন্ধানের জন্য are এই উত্তরটি সঠিক তবে লোকেরা এটি সন্ধান করছে না, কেবল একটি সহজ উত্তর। আমাকে নিজের থেকে সরল একটি সন্ধান করতে হয়েছিল তাই এটি এখানে রেখে দিন।
জেসন সেব্রিং

4
একটি লাইব্রেরির আকারে কোনও সমাধানের লিঙ্কটি পেস্ট না করে আসলে প্রশ্নটির উত্তর লেখার জন্য +1।
শন হোয়েনারি

56

কমই বেশি

আপনার প্রকল্পে প্রথমে কমান্ড প্রম্পট যান এবং ব্যবহার করুন

$ npm install express

তারপরে আপনার অ্যাপ.জেএস কোডটি লিখুন:

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

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

এরপরে আপনি একটি "সর্বজনীন" ফোল্ডার তৈরি করবেন যেখানে আপনি নিজের ফাইলগুলি রাখবেন। আমি প্রথমে এটি আরও কঠোরভাবে চেষ্টা করেছি তবে আপনাকে মাইম ধরণের সম্পর্কে চিন্তা করতে হবে যা কেবল সময়সাপেক্ষে স্টাফ ম্যাপ করতে হবে এবং তারপরে প্রতিক্রিয়ার ধরণ ইত্যাদি নিয়ে উদ্বিগ্ন হবে ইত্যাদি ইত্যাদি .... আপনাকে ধন্যবাদ না।


4
+1 আপনার নিজের ঘূর্ণায়মানের পরিবর্তে পরীক্ষিত কোড ব্যবহার করার জন্য অনেক কিছুই বলা যায়।
jcollum

4
আমি ডকুমেন্টেশনটি দেখার চেষ্টা করেছি, তবে খুব বেশি কিছু খুঁজে পাচ্ছি না, আপনি কী বলতে পারেন আপনার স্নিপেট কী করছে? আমি এই বিশেষ প্রকরণটি ব্যবহার করার চেষ্টা করেছি এবং কী কী দিয়ে প্রতিস্থাপন করা যায় তা আমি জানি না।
onaclov2000

4
আপনি যদি ডিরেক্টরি তালিকাটি চান, কেবল আপনার পথের সাহায্যে কানেক্ট.স্ট্যাটিক লাইনের ঠিক পরে ইউজ (কানেক্ট.ডাইরেক্টরি ('পাবলিক')) যুক্ত করুন public হাইজ্যাকিংয়ের জন্য দুঃখিত, তবে আমি মনে করি এটি আমার জন্য জিনিস পরিষ্কার করে দেয়।
onaclov2000

4
আপনি পাশাপাশি 'ব্যবহার করুন jQuery'! এটি ওপি-র প্রশ্নের দাবী নয়, এমন একটি সমস্যার সমাধান যা এমনকি অস্তিত্ব নেই। ওপি জানিয়েছে যে এই পরীক্ষার মূল বিষয়টি নোড শিখতে হয়েছিল।
শন হুইনারি

4
@ জেসনসেব্রিং require('http')দ্বিতীয় লাইনে কেন ?
ZenUML.com

20

আমি হুডের নীচে কী চলছে তা বুঝতে পছন্দ করি।

আমি আপনার কোডে কয়েকটি জিনিস লক্ষ্য করেছি যা আপনি সম্ভবত পরিষ্কার করতে চান:

  • যখন ফাইলের নামটি কোনও ডিরেক্টরিতে নির্দেশ করে তখন এটি ক্র্যাশ হয়, কারণ উপস্থিতটি সত্য এবং এটি কোনও ফাইল স্ট্রিম পড়ার চেষ্টা করে। ডিরেক্টরি অস্তিত্ব নির্ধারণ করতে আমি fs.lstatSync ব্যবহার করেছি।

  • এটি HTTP প্রতিক্রিয়া কোডগুলি সঠিকভাবে ব্যবহার করছে না (200, 404 ইত্যাদি)

  • মাইমটাইপ নির্ধারণ করা হচ্ছে (ফাইল এক্সটেনশন থেকে), এটি res.writHead এ সঠিকভাবে সেট করা যাচ্ছে না (স্টিও নির্দেশিত হিসাবে)

  • বিশেষ অক্ষরগুলি পরিচালনা করতে আপনি সম্ভবত ইউআরিকে ছাড়তে চান

  • এটি অন্ধভাবে চিহ্নগুলি অনুসরণ করে (এটি কোনও সুরক্ষার উদ্বেগ হতে পারে)

এটি দেওয়া, কিছু অ্যাপাচি অপশন (ফলোসিমলিংকস, শোইনডেক্সস, ইত্যাদি) আরও বোধগম্য হতে শুরু করে। আমি আপনার সরল ফাইল সার্ভারের জন্য কোডটি নিম্নরূপ আপডেট করেছি:

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 = mimeType [path.extname (ফাইলের নাম) .স্প্লিট ("। ")। বিপরীত () [0]];" পরিবর্তে? কিছু ফাইলের নাম একাধিক "" রয়েছে " যেমন "my.cool.video.mp4" বা "download.tar.gz"
অবিচ্ছিন্ন

এটি কি কোনওভাবে ফোল্ডার /../..//// হোম / ইউজার / জ্যাকপট.প্রাইভেটেকির মতো url ব্যবহার করা থেকে কাউকে বাধা দেয়? আমি পথটি নীচে প্রবাহিত হয়েছে তা নিশ্চিত করার জন্য জোড় দেখতে পাচ্ছি, তবে আমি ভাবছি .. ../../../ প্রকারের স্বরলিপিটি ব্যবহার করে এটি প্রায় পাওয়া যায় কিনা। সম্ভবত আমি নিজেই এটি পরীক্ষা করব।
রেইনার্ড

এটা কাজ করে না. আমি নিশ্চিত না কেন, তবে এটি জেনে ভাল লাগছে।
রেইনার্ড

চমৎকার, একটি রেজেক্স ম্যাচ এক্সটেনশন সংগ্রহ করতে পারে; 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);

4
সাফল্যের ক্ষেত্রে আপনি মাইমটাইপটি ভুলে গেছেন। আমি এই নকশাটি ব্যবহার করছি, তবে তাত্ক্ষণিকভাবে স্ট্রীমগুলি পাইপ করার পরিবর্তে, আমি সেগুলি ফাইল স্ট্রিমের 'উন্মুক্ত' ইভেন্টে পাইপ করছি: মাইমটাইপের জন্য রাইটহিড, তারপরে পাইপ। শেষের দরকার নেই: পঠনযোগ্য.পাইপ
জেএইচ

@ জিহ'এর মন্তব্য অনুসারে পরিবর্তিত হয়েছে।
ব্রেট জমির

হওয়া উচিতfileStream.on('open', ...
পেটা

2

আমি @ জেফ ওয়ার্ড উত্তরের উপর ভিত্তি করে সাধারণ ব্যবহারের জন্য অতিরিক্ত বৈশিষ্ট্য সহ একটি httpServer ফাংশন করেছি

  1. রীতিনীতি দির
  2. index.html req === dir হলে ফেরত দেয়

ব্যবহার:

httpServer(dir).listen(port);

https://github.com/kenokabe/ConciseStaticHttpServer

ধন্যবাদ


ইউআরএল এখন github.com/uplusplus/ConciseStaticHttpServer বলে মনে হচ্ছে
নেট অপারেটর উইব্বি

0

St মডিউল স্ট্যাটিক ফাইল সহজ ভজনা করে তোলে। এখানে 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

@ জেসনসেব্রিং উত্তর আমাকে সঠিক দিকে নির্দেশ করেছেন, তবে তার কোডটি পুরানো। আপনি কীভাবে এটি নতুন 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, তাই প্রযুক্তিগতভাবে আপনি সেই API গুলি ব্যবহার করে ব্যবহার করতে পারেন express.use()
ffleandro
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.