使用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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM