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
  • 相关阅读:
    孙权用人之道:“六力”兼备
    JDK 自带工具试用(一)
    Apache ab 测试工具使用(一)
    Amoeba详细介绍
    TCP/IP 标志位 SYN ACK RST UTG PSH FIN
    ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'mysql'
    jsp 中声明方法的使用
    Java遍历一个文件夹下的全部文件
    WAMP 2.5 &quot;FORBIDDEN&quot; error
    LeetCode总结--二分查找篇
  • 原文地址:https://www.cnblogs.com/zamhown/p/6429163.html
Copyright © 2011-2022 走看看