function(err, stats)第一个参数指示是否出现了错误,第二个参数是一个对象,类型是fs.Stats,保存了文件的状态信息,比如大小、创建时间、修改时间等。
FileServer的代码获取到文件状态后,读取大小,调用http.ServerResponse的writeHead方法,设置HTTP状态码为200,还设置了Content-Length头部。代码如下:
response.writeHead(200, {“Content-Type”: “text/plain”, “Content-Length”: stats.size})
ReadStream
接下来呢,我们调用fs.createReadStream创建了一个ReadStream对象。ReadStream是Stream,也是EventEmitter。
fs.createReadStream方法原型如下:
fs.createReadStream(path[, options])第一个参数是文件路径,第二个参数是可选的JSON对象,用来指定打开文件的一些选项,默认值如下:
{ flags: ‘r',
encoding: null,
fd: null,
mode: 0666,
autoClose: true
}autoClose属性默认为true,读完文件或读取出错时,文件会被自动关闭。fd属性可以关联一个已有的文件描述符,这样就会忽略path,根据一个已经打开的文件来创建流。options还可以有start和end项,指定起、止位置,读取文件的特定区域。如果我们要实现断点续传,就需要这个了,用法类似这样:
fs.createReadStream('sample.mp4', {start: 1000, end: 10000});encoding用来指定文件的编码,这对于文本文件有特殊的意义,目前支持’utf8’、’ascii’和’base64’。
ReadStream读取数据是异步的,一块一块的读,读到一部分就发送一个data事件,数据呢,会传递给与事件关联的listener(实际上是一个回调方法)。在我们的代码里,仅仅是调用response.write把数据写给客户端。注意,可能会多次调用response.write哦。又因为我们设置了Content-Length,所以不会采用chunked编码方式。如果我们不设置Content-Length,那默认会启用chunked方式。
ReadStream读完文件时会发射end事件,出错时会发射error事件,我们监听这两个事件,简单的终止响应。
我们在示例代码中看到了stream.on这种代码,下面来解释吧。
EventEmitter
Node.js基于V8引擎实现的事件驱动IO,是其最大最棒的特色之一。有了事件机制,就可以充分利用异步IO突破单线程编程模型的性能瓶颈,使得用JavaScript作后端开发有了实际意义。
EventEmitter的基本用法
events.EventEmitter是一个简单的事件发射器的实现,具有addListener、on、once、removeListener、emit等方法,开发者可以很方便的调用这些API监听某个事件或者发射某个事件。









