zoukankan      html  css  js  c++  java
  • 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 是文件的相对名称。
      • statfs.Stats文件对象。
    • path是完整的文件系统路径directory
    • style是默认样式表或stylesheet选项的内容
    • viewNameview选项提供的视图名称
    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

  • 相关阅读:
    Android:使用 DownloadManager 进行版本更新
    Android:UI 沉浸式体验,适合第一屏的引导图片、预览图片。
    Android:相机适配及图片处理的一些问题
    Android: 设置 app 字体大小不跟随系统字体调整而变化
    Android: TextView 及其子类通过代码和 XML 设置字体大小的存在差异的分析
    SQLMap 学习
    我的书单
    macos
    linux BufferedImage.createGraphics()卡住不动
    Linux 中ifconfig和ip addr命令看不到ip
  • 原文地址:https://www.cnblogs.com/zhaoweikai/p/9662572.html
Copyright © 2011-2022 走看看