標籤:
四、提供靜態檔案服務
1、建立一個靜態檔案伺服器
__dirname ,取值是該檔案所在咋目錄路徑。分散在不同目錄中的檔案可以有不同的值。
/** * 最進本的ReadStream靜態檔案伺服器 */var http = require(‘http‘);var parse = require(‘url‘).parse;var join = require(‘path‘).join;var fs = require(‘fs‘);var root = __dirname;var server = http.createServer(function(req,res){ var url = parse(req.url); var path = join(root,url.pathname); //構造絕對路徑 var stream = fs.createReadStream(path); //建立fs.ReadStream stream.on(‘data‘,function(chunk){ //將檔案資料寫到響應中 res.write(chunk); }); stream.on(‘end‘,function(){ res.end(); });});server.listen(3000);
這個檔案伺服器大體能用,但還有很多細節需要考慮。
管道和水管:
Node中的管道讓來自源頭(ReadableStream)的資料,流動到目的地(WriteableStream),我們用pipe方法把管道串連起來。
ReadableSteam.pipe(WriteableStream);
讀取一個檔案(ReadableStream)並把其中的內容寫到另一個檔案中(WriteableStream)用的就是管道
var readStream = fs.createReadSteam(‘./original.txt‘)var writeStream = fs.createwriteStrem(‘./copy.tet‘)readStream.pipe(writeStream)
所有ReadableStream都能接入任何一個WriteableStream。比如HTTP請求(req)對象就是ReadableStream.
2、處理伺服器錯誤
在Node中,所有整合了EventEmitter的類都可能發出error時間。
用fs.stat()實現先發制人的錯誤處理
因為傳輸的檔案是靜態,所以我們可以用stat()系統調用擷取檔案的相關資訊,比如修改時間、位元組數等。
/** *檢查檔案是否存在,並在響應中提供Content-Length */var server = http.createServer(function(req,res){ var url = parse(req.url); //解析URL以擷取路徑名 var path = join(root,url.pathname); fs.stat(path,function(err,stat){ //檢查檔案是否存在 if(err){ if(‘ENOENT‘ == err.code){ res.statusCode = 404; res.end(‘Not Found‘); }else{ res.setHeader(‘Content-Length‘,stat.size); //用Stat對象的屬性設定Content-Length var stream = fs.createReadStream(path); stream.pipe(res); stream.on(‘error‘,function(err){ res.statusCode = 500; res.end(‘Internal Server Error‘); }); } } });});
五、從表單中接受使用者輸入
1、處理提交的表單域
表單提交請求帶的Content-Type值通常有兩種
A、application/X-www-form-urlencoded: 這是HTML表單預設值
B、multipart/form-data: 在表單中含有檔案或非ASCII或位元據使用。
/** * 支援GET和POST的HTTP伺服器. */var http = require(‘http‘);var items = [];var server = http.createServer(function(req,res){ if(‘/‘ == req.url){ switch (req.method){ case ‘GET‘: show(res); break; case ‘POST‘: add(req,res); break; default: badRequest(res); } } else{ notFound(res); }});server.listen(3000);/*待辦事項清單頁面的表單和事項列表*/ function show(res){ var html = ‘<html><head><title>TODO LIST</title></head><body>‘ +‘<h1>TODO LIST</h1>‘ +‘<ul>‘ +items.map(function(item){ return ‘<li>‘+item+‘</li>‘ }).join(‘‘) +‘</ul>‘ +‘<form method="post" action="/">‘ +‘<p><input type="text" name="item" /></p>‘ +‘<p><input type="submit" value="Add Item" /></p>‘ +‘</form></body></html>‘; res.setHeader(‘Content-Type‘,‘text/html‘); res.setHeader(‘Content-Length‘,Buffer.byteLength(html)); res.end(html); }/*notFound()函數接受響應對象,將狀態嗎設為404,響應主體設為Not Found*/ function notFound(res){ res.statusCode = 404; res.setHeader(‘Content-Type‘,‘text/plain‘); res.end(‘NOT FOUND‘); }/*返回400 Bad Request響應的函數實現起來跟notFound()幾乎一樣*/ function badRequest(res){ res.statuCode = 400; res.setHeader(‘Content-Type‘,‘text/plain‘); res.end(‘BadRequest‘); }/*最後還要實現add()函數,它會接受req和res連個對象*/ var qs = require(‘querystring‘); function add(req,res){ var body=‘‘; req.setEncoding(‘utf8‘); req.on(‘data‘,function(chunk){ body += chunk; }); req.on(‘end‘,function(){ var obj = qs.parse(body); items.push(obj.item); show(res); }); }
NODE編程(四)--構建Node Web程式2