serve-index用法、实现原理(源码解读)
本文主要講解serve-index的用法和實現原理(源代碼分析)。
一 說明
serve-index的功能是將文件夾中文件列表顯示到瀏覽器中。
serve-index是一個NodeJS模塊,可以通過NPM安裝。
二 安裝方法
$ npm install serve-index --save
三 使用方法
通過ExpressJS創建靜態服務器時,使用serve-index方法如下:
1 var express = require('express');
2 var serveIndex = require('serve-index');
3 var app = express();
4
5 app.use(express.static('staticServer'));
6
7 app.use(serveIndex('staticServer',{ 'icons': true }));
8
9 var server = app.listen(3000, function () {
10 var host = server.address().address;
11 var port = server.address().port;
12
13 console.log('Example app listening at http://%s:%s', host, port);
14 });
通過nodeJS的serve-static創建靜態服務器時,用法如下:
1 var finalhandler = require('finalhandler')
2 var http = require('http')
3 var serveIndex = require('serve-index')
4 var serveStatic = require('serve-static')
5
6 // Serve directory indexes for public/ftp folder (with icons)
7 var index = serveIndex('public/ftp', {'icons': true})
8
9 // Serve up public/ftp folder files
10 var serve = serveStatic('public/ftp')
11
12 // Create server
13 var server = http.createServer(function onRequest(req, res){
14 var done = finalhandler(req, res)
15 serve(req, res, function onNext(err) {
16 if (err) return done(err)
17 index(req, res, done)
18 })
19 })
20
21 // Listen
22 server.listen(3000)
四 接口說明
serveIndex(path,options)
1.功能說明:
創建一個中間件函數。
2.返回值:
中間件函數,這個中間件創建了文件夾中所有文件的索引目錄。
3.參數:
path:
靜態文件服務器的路徑地址,一般與創建靜態服務器地址一致。
options:
ServeIndex在options對象中接受這些屬性:
filter
類型:Function;默認值為false。
功能:文件夾中每個文件都調用filter函數進行過濾,實際就是讓開發人員可以決定哪些文件顯示哪些不顯示,也可以改變文件名。如果該函數返回false(或者空字符串)【注意:只測試了這兩種】,則不顯示該文件夾。
參數:filter(filename, index, files, dir)
filename是文件名,index是數組索引,files是文件數組,是文件dir所在的絕對路徑。
下邊是filter的一個示例,用于過濾不顯示READEME.md文件。
1 var options = {
2 icons : true,
3 filter : serveIndexFilter
4 };
5
6 function serveIndexFilter(filename, index, list, path) {
7 console.log(filename);
8 console.log(index);
9 console.log(list);
10 console.log(path);
11
12 // 過濾README.md文件,如果是該文件,就不顯示
13 if (filename.match('README.md')) {
14 return '';
15 } else {
16 return filename;
17 }
18 }
19
20 app.use(serveIndex('staticServer', options));
hidden
類型:Boolean
默認值:false
功能:是否隱藏文件名是“.”的文件。設置為true時,顯示;設置為false時,不顯示。
icons
顯示文件圖標。默認為false。
stylesheet
CSS樣式表的可選路徑。默認為內置樣式表。
template
HTML模板的可選路徑或將呈現HTML字符串的函數。默認為內置模板。
給定字符串時,該字符串將用作要加載的文件路徑,然后在模板中替換以下標記:
{directory}使用目錄的名稱。
{files}使用無序的文件鏈接列表的HTML。
{linked-path}使用目錄鏈接的HTML。
{style}使用指定的樣式表和嵌入的圖像。
當作為函數給出時,該函數被調用為template(locals, callback),并且需要調用它callback(error, htmlString)。以下是提供的當地人:
directory是顯示的目錄(/根在哪里)。
displayIcons是否應該呈現圖標的布爾值。
fileList是目錄中的已排序文件數組。該數組包含具有以下屬性的對象:
name是文件的相對名稱。
stat是fs.Stats文件的對象。
path是完整的文件系統路徑directory。
style是默認樣式表或stylesheet選項的內容。
viewName是view選項提供的視圖名稱。
view
類型:String
功能:顯示模式。可選值:"tiles"、"details"。默認為tiles。
說明:設置為details時,顯示樣子如下:
五 實現原理
通過上邊用法可以知道,serveIndex方法返回一個中間件函數,這個中間件函數會在服務器接收到請求時執行,這個函數的主要功能是根據請求url地址,讀取本地文件夾中對應的文件,創建一個HTML文件,生成文件列表DOM、樣式等插入HTML文件中,并將這個HTML作為請求內容返回給瀏覽器顯示,這樣就實現了將文件夾內容顯示到瀏覽器中了。
詳細步驟如下:
5.1.serveIndex方法創建并返回中間件函數,該中間件函數作為app.use()的參數,這樣就相當于給服務器注冊了一個回調函數,當有請求過來時,就會調用該函數。
app.use(serveIndex('staticServer', options));
serveIndex的縮略代碼(省去了返回的函數代碼)如下:
1 function serveIndex(root, options) {
2 var opts = options || {};
3
4 // root required
5 if (!root) {
6 throw new TypeError('serveIndex() root path required');
7 }
8
9 // resolve root to absolute and normalize
10 var rootPath = normalize(resolve(root) + sep);
11
12 var filter = opts.filter;
13 var hidden = opts.hidden;
14 var icons = opts.icons;
15 var stylesheet = opts.stylesheet || defaultStylesheet;
16 var template = opts.template || defaultTemplate;
17 var view = opts.view || 'tiles';
18
19 return function (req, res, next) {
20 //...
21 };
22 };
5.2 當服務器受到瀏覽器請求時,會執行上邊返回的中間的函數,該函數主要功能是根據請求url地址,讀取本地文件夾中對應的文件,創建一個HTML文件,生成文件列表DOM、樣式等插入HTML文件中,并將這個HTML作為請求內容返回給瀏覽器顯示,這樣就實現了將文件夾內容顯示到瀏覽器中了。
重點代碼片段如下:
通過NodeJS的fs文件接口讀取請求路徑中的文件:
1 fs.readdir(path, function(err, files){
2 if (err) return next(err);
3 if (!hidden) files = removeHidden(files);
4 if (filter) files = files.filter(function(filename, index, list) {
5 return filter(filename, index, list, path);
6 });
7 files.sort();
8
9 // content-negotiation
10 var accept = accepts(req);
11 var type = accept.type(mediaTypes);
12
13 // not acceptable
14 if (!type) return next(createError(406));
15 serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet);
16 });
上邊代碼中最后調用的serveIndex[mediaType[type]],實際是調用serveIndex.html()方法,該方法主要做了2件事:創建HTML文件和文件列表DOM,并設置給請求頭的body中。
1 fs.readFile(stylesheet, 'utf8', function (err, style) {
2 if (err) return next(err);
3
4 // create locals for rendering
5 var locals = {
6 directory: dir,
7 displayIcons: Boolean(icons),
8 fileList: fileList,
9 path: path,
10 style: style,
11 viewName: view
12 };
13
14 // render html
15 render(locals, function (err, body) {
16 if (err) return next(err);
17 send(res, 'text/html', body)
18 });
19 });
1 function createHtmlRender(template) {
2 return function render(locals, callback) {
3 // read template
4 fs.readFile(template, 'utf8', function (err, str) {
5 if (err) return callback(err);
6
7 var body = str
8 .replace(/{style}/g, locals.style.concat(iconStyle(locals.fileList, locals.displayIcons)))
9 .replace(/{files}/g, createHtmlFileList(locals.fileList, locals.directory, locals.displayIcons, locals.viewName))
10 .replace(/{directory}/g, escapeHtml(locals.directory))
11 .replace(/{linked-path}/g, htmlPath(locals.directory));
12
13 callback(null, body);
14 });
15 };
16 }
1 function send (res, type, body) {
2 // security header for content sniffing
3 res.setHeader('X-Content-Type-Options', 'nosniff')
4
5 // standard headers
6 res.setHeader('Content-Type', type + '; charset=utf-8')
7 res.setHeader('Content-Length', Buffer.byteLength(body, 'utf8'))
8
9 // body
10 res.end(body, 'utf8')
11 }
參考資料&內容來源:
Express官網:http://www.expressjs.com.cn/en/resources/middleware/serve-index.html
總結
以上是生活随笔為你收集整理的serve-index用法、实现原理(源码解读)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七天学会SALTSTACK自动化运维 (
- 下一篇: Hibernate之工具类Hiberna