一、开篇分析。
文件系统模块是一组简单打包的标准POSIX文件I/O操作方法。您可以通过调用require('fs ')来获取模块。文件系统模块中的所有方法都有异步和同步版本。
(1)文件系统模块中的异步方法作为最后一个传入参数完成时需要回调函数。
(2)回调函数的组成由调用的异步方法决定。通常,回调函数的第一个参数是返回的错误信息。
(3)如果异步操作执行正确并返回,则错误参数为空或未定义。如果使用同步版本的操作方法,一旦发生错误,将以抛出错误的通常形式返回错误。
(4) try和catch语句可用于截取错误并使程序继续运行。
让我们看一个简单的例子。读取文件(' bb.txt'):
(1)、创建文件‘bb . txt’,内容如下(“大家好,我是大雄君!(* _ _ *)嘻嘻……”).
(2)、读取文件操作如下:
复制代码如下: var fs=require(' fs ');fs.readFile('bb.txt ',' utf8 ',函数(错误,数据){ if(错误)引发错误;console.log(数据);}) ;
运行结果:
这里需要注意的是,读取文件时必须设置代码,否则默认会以“缓冲区”的形式出现。
看没有设置的操作效果,差别很明显。如下所示:
下面是另一个写操作,如下所示:
复制代码如下: var fs=require(' fs ');Var txt='大家要好好学习NodeJS!';//写入文件fs.writefile ('bb.txt ',txt,function(err){ if(err)throw err;控制台.日志('文件已保存!');//文件已保存});
运行结果:
在一些常用示例列表中:
复制代码如下://删除文件fs.unlink ('bb.txt ',function(){ console . log(' success ');}) ;//修改文件名fs.rename ('bb.txt ',' bigbear.txt ',函数(err){ console . log(' rename success ');});//检查文件状态fs.stat ('bb.txt ',函数(err,stat){ console . log(stat);});//判断文件是否有fs.exists ('bb.txt ',function(exists){ console . log(exists);}) ;
第二,Fs和Stream的关系。
“Stream”是异步的。我可以把一个文件或者一段内容分成未知的‘块’来读,每次读‘块’的时候,我们都会输出。直到文件被读取。这就像“http1.1”支持的“传输编码:分块”一样。(“chunk”可以以任何形式存在,NodeJS默认以“Buffer”的形式存在,效率更高)。NodeJS中的“Stream”在Unix系统中有一个超级特性(“管道”)。
还记得“Http模块”中的第一个NodeJS程序,‘你好,大熊!’是吗?我们基于那个小程序做了一个修改,代码如下:
(1)、建立“bb.html”。
复制的代码如下: HTML Head Style Type=' text/CSS ' div { margin-top : 50px;宽度: 100%;margin: 0px高度:120 px;行高:120 px;color: # ffffont-size :22 px;背景# ff9900文本对齐:中心;}/风格/头身divHello,大熊!/div /body/html
(2)修改前的程序如下:
复制代码如下: var http=require(' http ');var fs=require(' fs ');var server=http . createserver(function(req,res){ fs.readFile('bb.html ',' utf-8 ',function(err,data){ if(err){ RES . write head(500,{ ' Context-Type ' : ' text/plain ' });res.end('指定文件不存在!或者服务器错误!”);} else{ res.writeHead(200,{ ' Context-Type ' : ' text/html ' });res.write(数据);RES . end();} })}) ;server . listen(8888);console.log('在端口8888上运行的http服务器.') ;
以下是运行结果:
现在我们需要考虑一下,如果我们想发送超媒体文件而不是简单的文本文件,比如谷歌2014 IO大会的全高清视频文件。Mp4格式。长度超过2小时1080p。
大概四个多英国。已知"读取文件"的工作方式是将文件读取到内存。那么这么大一个文件显然是不能这么做的。那该怎么办呢?是之后就需要使用溪流的来做。那么是这样的。
代码如下像这样:
复制代码代码如下: fs。createReadStream(_ dirname/)vedio。MP4 ').管道(RES);
总结一下:
这些代码可以实现需要的功能,但是服务在发送文件数据之前需要缓存整个文件数据到内存,如果bb.html文件很大并且并发量很大的话,会浪费很多内存。因为用户需要等到整个文件缓存到内存才能接受的文件数据,这样导致用户体验相当不好。不过还好(请求,决议)两个参数都是小溪,这样我们可以用fs.createReadStream()代替fs.readFile()'。
三,实例
来一个文件上传的小栗子:
(1),建立" server.js "
复制代码代码如下: var http=require(' http ');var URL=必选(' URL ');函数开始(路由,处理程序){请求(请求,响应)上的函数} { var pathname=URL。解析(请求。网址).路径名;//路由到相应的业务逻辑路由(路径名、处理程序、响应、请求);} http.createServer(onRequest).听(3000);console.log('服务器正在启动');} exports.start=start
(2),建立" route.js "
复制代码代码如下:函数路由(路径名、处理程序、响应、请求){ console.log('即将为路径名路由请求);if(处理程序类型[pathname]==' function "){返回处理程序[pathname](响应,请求);} else { console。日志('路径名'找不到请求处理程序);response.writeHead(404,{ ' Content-Type ' : ' text/html ' });响应。写入(' 404未找到!');回应。end();} } exports.route=route
(3),建立" requestHandler.js "
复制代码代码如下: var查询字符串=require('查询字符串')、fs=require('fs ')、removable=require(' removable ');函数开始(响应,请求){控制台。日志(“启动模块”);var body=' html ' ' head ' ' meta http-equiv=' Content-Type ' ' ' Content=' text/html;charset=UTF-8 '/' '/head ' ' body ' '表单操作='/upload ' enctype=' multipart/form-data '方法=“发布”输入类型='文件'名称='上传'多个='多个'输入类型='提交'值='提交文本'/' '/表单' '/正文' '/html ';response.writeHead(200,{ ' Content-Type ' : ' text/html ' });response.write(正文);回应。end();}函数上传(响应、请求){ console.log('上传模块');定义变量形式=新的强大IncomingForm();form.parse(请求,函数(错误,字段,文件){ fs。renamesync(文件。上传。路径,'/tmp/test。png ');response.writeHead(200,{ ' Content-Type ' : ' text/html ' });回应。写下('你已经发送了: br/');回应。write(' img src=' http :/show '/');回应。end();});}函数显示(响应,请求){控制台。日志('显示模块');fs.readFile ('/tmp/test.png ','二进制',函数(错误,文件){ if(错误){ response.writeHead(200,{ ' Content-Type ' : ' text/html ' });response.write(错误);回应。end();} else { response.writeHead(200,{ ' Content-Type ' : ' image/png ' });response.write(文件,' binary ');回应。end();} });} exports . start=startexports . upload=上传;exports.show=show
(4),建立" index.js "
复制代码代码如下:var server=require(' ./server’);var router=require(' ./router’);var requestHandler=require(' ./RequestHandler ');定义变量令人生畏=require('令人生畏');//需要路径搜索算法?定义变量处理程序={ };处理程序['/']=RequestHandler。开始;处理程序['/start ']=RequestHandler。开始;处理程序['/upload ']=RequestHandler。上传;处理程序['/show ']=RequestHandler。展示;server.start(router.route,handler);
四,总结一下
(1),理解满量程与溪流之间的联系。(2),熟练使用' FS '相关的api。(3),注意细节的把控,比如:文件操作美国石油学会(美国石油协会)同步方式与异步方式之间的处理细节。(4),最后强调:理解文件上传例子中的代码组织方式,不断重构,不断总结。