亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Node.js創(chuàng)建HTTP文件服務(wù)器的使用示例

 更新時(shí)間:2018年05月11日 10:48:37   作者:foruok  
我們的目的比較簡(jiǎn)單,使用Node.js創(chuàng)建一個(gè)HTTP協(xié)議的文件服務(wù)器,你可以使用瀏覽器或其它下載工具到文件服務(wù)器上下載文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

HelloWorld示例只有演示意義,這次我們來(lái)搞一個(gè)實(shí)際的例子:文件服務(wù)器。我們使用Node.js創(chuàng)建一個(gè)HTTP協(xié)議的文件服務(wù)器,你可以使用瀏覽器或其它下載工具到文件服務(wù)器上下載文件。

為了讀取文件,我們會(huì)用到File System模塊(名字是”fs”),Stream,我們還要分析URL,區(qū)別HTTP方法,還會(huì)用到EventEmitter。

文件服務(wù)器FileServer的代碼

先上代碼吧,依然是簡(jiǎn)單的:

// 引入http模塊
var http = require("http"); 
var fs = require("fs");

// 創(chuàng)建server,指定處理客戶端請(qǐng)求的函數(shù)
http.createServer(
  function(request, response) {
    //判斷HTTP方法,只處理GET 
    if(request.method != "GET"){
      response.writeHead(403);
      response.end();
      return null;
    }

    //此處也可使用URL模塊來(lái)分析URL(https://nodejs.org/api/url.html)
    var sep = request.url.indexOf('?');
    var filePath = sep < 0 ? request.url : request.url.slice(0, sep);
    console.log("GET file: " + filePath);

    //當(dāng)文件存在時(shí)發(fā)送數(shù)據(jù)給客戶端,否則404
    var fileStat = fs.stat("."+filePath, 
      function(err, stats){
        if(err) {
          response.writeHead(404);
          response.end();
          return null;
        }
        //TODO:Content-Type應(yīng)該根據(jù)文件類型設(shè)置
        response.writeHead(200, {"Content-Type": "text/plain", "Content-Length": stats.size});

        //使用Stream
        var stream = fs.createReadStream("."+filePath);

        stream.on('data',function(chunk){
          response.write(chunk);
        });

        stream.on('end',function(){
          response.end();
        });

        stream.on('error',function(){
          response.end();
        });
      }
    );
  }
).listen(8000); 

console.log("Hello World start listen on port 8000");

最大的變化,就在傳遞給createServer方法的參數(shù)了。

我們根據(jù)request.method作了判斷,不是GET就返回403。如果是呢,就判斷文件是否存在,不存在,返回404,存在就讀取數(shù)據(jù)寫(xiě)給客戶端。邏輯就是這么簡(jiǎn)單。下面我們來(lái)介紹用到的新知識(shí)。

File System

要使用FileSystem,得用require引入fs模塊,就如前面代碼里那樣。File System的API老長(zhǎng)老長(zhǎng)了,看這里吧:https://nodejs.org/api/fs.html。我們只說(shuō)用到的特性。

獲取文件狀態(tài)

在我們的FileServer里,收到和客戶端請(qǐng)求時(shí)先通過(guò)fs.stat()方法獲取文件狀態(tài)。fs.stat()方法原型如下:

fs.stat(path, callback)

第一個(gè)參數(shù)是文件路徑,第二個(gè)參數(shù)是回調(diào)函數(shù)。fs.stat()方法是異步的,結(jié)果通過(guò)回調(diào)函數(shù)callback返回。callback的原型如下:

function(err, stats)

第一個(gè)參數(shù)指示是否出現(xiàn)了錯(cuò)誤,第二個(gè)參數(shù)是一個(gè)對(duì)象,類型是fs.Stats,保存了文件的狀態(tài)信息,比如大小、創(chuàng)建時(shí)間、修改時(shí)間等。

FileServer的代碼獲取到文件狀態(tài)后,讀取大小,調(diào)用http.ServerResponse的writeHead方法,設(shè)置HTTP狀態(tài)碼為200,還設(shè)置了Content-Length頭部。代碼如下:

復(fù)制代碼 代碼如下:
response.writeHead(200, {"Content-Type": "text/plain", "Content-Length": stats.size})

ReadStream

接下來(lái)呢,我們調(diào)用fs.createReadStream創(chuàng)建了一個(gè)ReadStream對(duì)象。ReadStream是Stream,也是EventEmitter。

fs.createReadStream方法原型如下:

fs.createReadStream(path[, options])

第一個(gè)參數(shù)是文件路徑,第二個(gè)參數(shù)是可選的JSON對(duì)象,用來(lái)指定打開(kāi)文件的一些選項(xiàng),默認(rèn)值如下:

{ flags: ‘r', 
encoding: null, 
fd: null, 
mode: 0666, 
autoClose: true 
}

autoClose屬性默認(rèn)為true,讀完文件或讀取出錯(cuò)時(shí),文件會(huì)被自動(dòng)關(guān)閉。fd屬性可以關(guān)聯(lián)一個(gè)已有的文件描述符,這樣就會(huì)忽略path,根據(jù)一個(gè)已經(jīng)打開(kāi)的文件來(lái)創(chuàng)建流。options還可以有start和end項(xiàng),指定起、止位置,讀取文件的特定區(qū)域。如果我們要實(shí)現(xiàn)斷點(diǎn)續(xù)傳,就需要這個(gè)了,用法類似這樣:

fs.createReadStream('sample.mp4', {start: 1000, end: 10000});

encoding用來(lái)指定文件的編碼,這對(duì)于文本文件有特殊的意義,目前支持'utf8'、'ascii'和'base64'。

ReadStream讀取數(shù)據(jù)是異步的,一塊一塊的讀,讀到一部分就發(fā)送一個(gè)data事件,數(shù)據(jù)呢,會(huì)傳遞給與事件關(guān)聯(lián)的listener(實(shí)際上是一個(gè)回調(diào)方法)。在我們的代碼里,僅僅是調(diào)用response.write把數(shù)據(jù)寫(xiě)給客戶端。注意,可能會(huì)多次調(diào)用response.write哦。又因?yàn)槲覀冊(cè)O(shè)置了Content-Length,所以不會(huì)采用chunked編碼方式。如果我們不設(shè)置Content-Length,那默認(rèn)會(huì)啟用chunked方式。

ReadStream讀完文件時(shí)會(huì)發(fā)射end事件,出錯(cuò)時(shí)會(huì)發(fā)射error事件,我們監(jiān)聽(tīng)這兩個(gè)事件,簡(jiǎn)單的終止響應(yīng)。

我們?cè)谑纠a中看到了stream.on這種代碼,下面來(lái)解釋吧。

EventEmitter

Node.js基于V8引擎實(shí)現(xiàn)的事件驅(qū)動(dòng)IO,是其最大最棒的特色之一。有了事件機(jī)制,就可以充分利用異步IO突破單線程編程模型的性能瓶頸,使得用JavaScript作后端開(kāi)發(fā)有了實(shí)際意義。

EventEmitter的基本用法

events.EventEmitter是一個(gè)簡(jiǎn)單的事件發(fā)射器的實(shí)現(xiàn),具有addListener、on、once、removeListener、emit等方法,開(kāi)發(fā)者可以很方便的調(diào)用這些API監(jiān)聽(tīng)某個(gè)事件或者發(fā)射某個(gè)事件。

我們?cè)谑纠杏玫降?a target="_blank" rel="external nofollow" >fs.ReadStream就是一個(gè)EventEmitter,它實(shí)現(xiàn)了stream.Readable接口,而stream.Readable具有data、error、end、close、readable等事件。

通常我們使用EventEmitter的on或addListener來(lái)監(jiān)聽(tīng)一個(gè)事件,這個(gè)時(shí)間可能會(huì)多次觸發(fā),每次觸發(fā),我們提供的回調(diào)方法都會(huì)被調(diào)用。我們示例中的代碼就是這樣:

    stream.on('data',function(chunk){
      response.write(chunk);
    });

Node.js的事件機(jī)制,會(huì)給某個(gè)事件關(guān)聯(lián)一個(gè)回調(diào)方法列表,這樣多個(gè)關(guān)注者就可以監(jiān)聽(tīng)同一個(gè)事件。每個(gè)事件發(fā)射時(shí),可能會(huì)帶有數(shù)據(jù)和狀態(tài),這些數(shù)據(jù)是通過(guò)回調(diào)方法的參數(shù)傳遞出來(lái)的。那某一個(gè)特定的事件,它對(duì)應(yīng)的回調(diào)方法的參數(shù)是什么樣子的,則由事件定義的那個(gè)類(實(shí)例)來(lái)決定。EventEmitter的emit方法原型如下:

emitter.emit(event[, arg1][, arg2][, ...])

這個(gè)原型說(shuō)明一個(gè)事件的回調(diào)方法可以有一個(gè)或多個(gè)參數(shù),也可以沒(méi)有參數(shù)。要想知道某個(gè)事件的回調(diào)方法是否有參數(shù)、每個(gè)參數(shù)的含義,只好去找相關(guān)的API文檔。stream.Readable的data事件的參數(shù)是chunk,Buffer類型,代表讀到的數(shù)據(jù)。

如果我們只想監(jiān)聽(tīng)某個(gè)事件一次,則可以調(diào)用EventEmitter的once方法。要想移除一個(gè)事件監(jiān)聽(tīng)器,可以調(diào)用removeListener,想移除所有,則可以調(diào)用removeAllListener。

自定義事件

Node.js的很多模塊都繼承自Event模塊。我們自己也可以通過(guò)繼承EventEmitter來(lái)實(shí)現(xiàn)自己的對(duì)象,添加自己的自定義事件。

這里有個(gè)簡(jiǎn)單的例子:

var util=require("util");
var events = require("events");
function Ticker() {
  var self = this;
  events.EventEmitter.call(this);
  setInterval(function(){
    self.emit("tick")
    },
    1000
  );
}
util.inherits(Ticker, events.EventEmitter);

var ticker = new Ticker();
ticker.on("tick", function() {
 console.log("tick event");
});

在這個(gè)簡(jiǎn)單的例子里,我們定義了Ticker對(duì)象,通過(guò)全局方法setInterval開(kāi)啟了一個(gè)定時(shí)器,每隔1000毫秒發(fā)射一個(gè)名為“tick”的事件。

Node.js的工具模塊封裝了繼承的方法,我們調(diào)用它來(lái)的inherits方法來(lái)完成Ticker對(duì)events.EventEmitter的繼承。

自定義事件的使用方法,和Node.js內(nèi)置模塊提供的事件的用法完全一樣。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 安裝node.js和npm的一些常見(jiàn)報(bào)錯(cuò)

    安裝node.js和npm的一些常見(jiàn)報(bào)錯(cuò)

    NVM(Node?Version?Manager)是一個(gè)用于在同一機(jī)器上同時(shí)安裝并管理多個(gè)Node.js版本的工具,這篇文章主要給大家介紹了關(guān)于安裝node.js和npm的一些常見(jiàn)報(bào)錯(cuò),需要的朋友可以參考下
    2023-06-06
  • nodejs實(shí)現(xiàn)bigpipe異步加載頁(yè)面方案

    nodejs實(shí)現(xiàn)bigpipe異步加載頁(yè)面方案

    本文給大家分享的是使用nodejs結(jié)合bigpipe實(shí)現(xiàn)異步加載頁(yè)面的方案,非常的實(shí)用,也是以后前端性能優(yōu)化的一個(gè)方向,希望大家能夠喜歡。
    2016-01-01
  • Node.js的cross-env工具包使用介紹

    Node.js的cross-env工具包使用介紹

    這篇文章主要為大家介紹了Node.js的cross-env工具包使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 淺談Node的內(nèi)存泄露

    淺談Node的內(nèi)存泄露

    隨著node、react同構(gòu)等技術(shù)越來(lái)越廣泛地使用, 內(nèi)存泄漏的事情時(shí)有發(fā)生,應(yīng)當(dāng)引起足夠的重視,本文主要介紹了Node的內(nèi)存泄露,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 深入理解Node.js中通用基礎(chǔ)設(shè)計(jì)模式

    深入理解Node.js中通用基礎(chǔ)設(shè)計(jì)模式

    大家在談到設(shè)計(jì)模式時(shí)最先想到的就是 singletons, observers(觀察者) 或 factories(工廠方法)。本文重點(diǎn)給大家介紹Node.JS一些基礎(chǔ)模式的實(shí)現(xiàn)方法,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2017-09-09
  • Nodejs中crypto模塊的安全知識(shí)講解

    Nodejs中crypto模塊的安全知識(shí)講解

    本篇文章給大家詳細(xì)介紹了Nodejs中crypto模塊的安全知識(shí)的相關(guān)內(nèi)容,需要的朋友跟著小編一下學(xué)習(xí)參考下吧。
    2018-01-01
  • 關(guān)于NodeJS中的循環(huán)引用詳解

    關(guān)于NodeJS中的循環(huán)引用詳解

    這篇文章主要給大家介紹了關(guān)于NodeJS中的循環(huán)引用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用NodeJS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • node.js中的fs.readFile方法使用說(shuō)明

    node.js中的fs.readFile方法使用說(shuō)明

    這篇文章主要介紹了node.js中的fs.readFile方法使用說(shuō)明,本文介紹了fs.readFile的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • package.json文件配置詳解

    package.json文件配置詳解

    這篇文章主要介紹了package.json文件配置詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-06-06
  • NodeJS學(xué)習(xí)筆記之(Url,QueryString,Path)模塊

    NodeJS學(xué)習(xí)筆記之(Url,QueryString,Path)模塊

    今天我們來(lái)看一下在nodejs中路徑的相關(guān)操作方法。在我們開(kāi)發(fā)過(guò)程中路徑主要有:URL路徑,在瀏覽器中進(jìn)行使用,當(dāng)然這個(gè)也包含查詢字符串QueryString的相關(guān)操作;而另一種是磁盤(pán)路徑,主要用于文件等等進(jìn)行操作,我們稱為Path,所以我將它們放在一起進(jìn)行總結(jié)學(xué)習(xí)。
    2015-01-01

最新評(píng)論