zoukankan      html  css  js  c++  java
  • 使用Node.js快速搭建简单的静态文件服务器

    做前端有时会采用一些复杂框架,在文件系统中直接打开页面(用file:///方式打开),往往会报跨域的错,类似于“XMLHttpRequest cannot load ...(文件名). Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.”。这时,我们可以快速搭建一个简单的静态文件服务器,用Node.js最合适。

    看过龍太的文章后(地址:http://www.jianshu.com/p/76c1a9f39a36),我觉得这篇文章里的服务器实现还是“麻雀虽小,五脏俱全”的。不过代码有Bug,比如当用户请求一个目录时,代码虽然可以自动搜索目录里的index.html,但在显示过程中出现异常。经过研究和修改,我把原文章中的3个js脚本合为一个,并解决了这个问题。而且优化了体验,比如当运行这个js文件时,载入项目主页的浏览器会自动弹出来。

    1.在前端项目根目录下创建server.js,代码如下:

      1 "use strict";
      2 //加载所需要的模块
      3 var http = require('http');
      4 var url = require('url');
      5 var fs = require('fs');
      6 var path = require('path');
      7 var cp = require('child_process');
      8 
      9 //创建服务
     10 var httpServer = http.createServer(processRequest);
     11 
     12 var port = 8080;
     13 
     14 //指定一个监听的接口
     15 httpServer.listen(port, function() {
     16     console.log(`app is running at port:${port}`);
     17     console.log(`url: http://localhost:${port}`);
     18     cp.exec(`explorer http://localhost:${port}`, function () {
     19     });
     20 });
     21 
     22 //响应请求的函数
     23 function processRequest (request, response) {
     24     //mime类型
     25     var mime = {
     26         "css": "text/css",
     27         "gif": "image/gif",
     28         "html": "text/html",
     29         "ico": "image/x-icon",
     30         "jpeg": "image/jpeg",
     31         "jpg": "image/jpeg",
     32         "js": "text/javascript",
     33         "json": "application/json",
     34         "pdf": "application/pdf",
     35         "png": "image/png",
     36         "svg": "image/svg+xml",
     37         "swf": "application/x-shockwave-flash",
     38         "tiff": "image/tiff",
     39         "txt": "text/plain",
     40         "wav": "audio/x-wav",
     41         "wma": "audio/x-ms-wma",
     42         "wmv": "video/x-ms-wmv",
     43         "xml": "text/xml"
     44     };
     45     
     46     //request里面切出标识符字符串
     47     var requestUrl = request.url;
     48     //url模块的parse方法 接受一个字符串,返回一个url对象,切出来路径
     49     var pathName = url.parse(requestUrl).pathname;
     50 
     51     //对路径解码,防止中文乱码
     52     var pathName = decodeURI(pathName);
     53 
     54     //解决301重定向问题,如果pathname没以/结尾,并且没有扩展名
     55     if (!pathName.endsWith('/') && path.extname(pathName) === '') {
     56         pathName += '/';
     57         var redirect = "http://" + request.headers.host + pathName;
     58         response.writeHead(301, {
     59             location: redirect
     60         });
     61         //response.end方法用来回应完成后关闭本次对话,也可以写入HTTP回应的具体内容。
     62         response.end();
     63     }
     64 
     65     //获取资源文件的绝对路径
     66     var filePath = path.resolve(__dirname + pathName);
     67     console.log(filePath);
     68     //获取对应文件的文档类型
     69     //我们通过path.extname来获取文件的后缀名。由于extname返回值包含”.”,所以通过slice方法来剔除掉”.”,
     70     //对于没有后缀名的文件,我们一律认为是unknown。
     71     var ext = path.extname(pathName);
     72     ext = ext ? ext.slice(1) : 'unknown';
     73 
     74     //未知的类型一律用"text/plain"类型
     75     var contentType = mime[ext] || "text/plain";
     76 
     77     fs.stat(filePath, (err, stats) => {
     78         if (err) {
     79             response.writeHead(404, { "content-type": "text/html" });
     80             response.end("<h1>404 Not Found</h1>");
     81         }
     82         //没出错 并且文件存在
     83         if (!err && stats.isFile()) {
     84             readFile(filePath, contentType);
     85         }
     86         //如果路径是目录
     87         if (!err && stats.isDirectory()) {
     88             var html = "<head><meta charset = 'utf-8'/></head><body><ul>";
     89             //读取该路径下文件
     90             fs.readdir(filePath, (err, files) => {
     91                 if (err) {
     92                     console.log("读取路径失败!");
     93                 } else {
     94                     //做成一个链接表,方便用户访问
     95                     var flag = false;
     96                     for (var file of files) {
     97                         //如果在目录下找到index.html,直接读取这个文件
     98                         if (file === "index.html") {
     99                             readFile(filePath + (filePath[filePath.length-1]=='/' ? '' : '/') + 'index.html', "text/html");
    100                             flag = true;
    101                             break;
    102                         };
    103                         html += `<li><a href='${file}'>${file}</a></li>`;
    104                     }
    105                     if(!flag) {
    106                         html += '</ul></body>';
    107                         response.writeHead(200, { "content-type": "text/html" });
    108                         response.end(html);
    109                     }
    110                 }
    111             });
    112         }
    113 
    114         //读取文件的函数
    115         function readFile(filePath, contentType){
    116             response.writeHead(200, { "content-type": contentType });
    117             //建立流对象,读文件
    118             var stream = fs.createReadStream(filePath);
    119             //错误处理
    120             stream.on('error', function() {
    121                 response.writeHead(500, { "content-type": contentType });
    122                 response.end("<h1>500 Server Error</h1>");
    123             });
    124             //读取文件
    125             stream.pipe(response);
    126         }
    127     });
    128 }

    2.在前端项目根目录下打开命令提示符或终端,输入以下命令就可以启动小服务器啦。

    node server.js
  • 相关阅读:
    Notes of Daily Scrum Meeting(12.18)
    Notes of Daily Scrum Meeting(12.17)
    Notes of Daily Scrum Meeting(12.16)
    Notes of Daily Scrum Meeting(12.8)
    Notes of Daily Scrum Meeting(12.5)
    Notes of Daily Scrum Meeting(12.3)
    Notes of Daily Scrum Meeting(11.12)
    Linux中profile、bashrc、bash_profile之间的区别和联系
    Linux GCC编译
    mysql 5.7.16 远程连接
  • 原文地址:https://www.cnblogs.com/zamhown/p/6429163.html
Copyright © 2011-2022 走看看