1. 程式人生 > >[Nodejs] node實現靜態文件服務器

[Nodejs] node實現靜態文件服務器

-m func quest === web 標準 svg isf 之前

node 靜態文件處理

一般後端進行靜態文件處理都是使用 Apache nginx 等靜態 web 服務器,但是既然使用 node 了,就用 node 實現以下靜態服務器吧.

之前弄了不少充滿藝術的數據,就弄個頁面進行藝術欣賞吧

app.js

    "/": (request, response) => {
      response.writeHead(200, { "content-type": "text/html;charset=utf-8" });
      let stream = fs.createReadStream(
        path.join(__dirname, "/views/index.html")
      );
      stream.on("error", function() {
        response.writeHead(500, { "content-type": "text/html;charset=utf-8" });
        response.end("<h1>500 Server Error</h1>");
      });
      stream.pipe(response);
    },

views/index.html/index.js/index.css

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>時尚風範</title>
    <link rel="stylesheet" href="./index.css" type="text/css" />
    <script src="./index.js"></script>
  </head>
  <body>
    <div class="img-list">
      <div class="header">我是寫真集</header>
    </div>
  </body>
</html>

技術分享圖片
但是打開之後什麽都不能看,css 和 js 在控制臺都是 404 顯示.因為服務器沒有寫相應的代碼去處理這些文件,所以接收到請求,服務器也是一臉茫然,不知道究竟要幹什麽.

所有我們要對請求的資源做出相對應的回答,那怕是個 404

添加 css 和 js 的支持

"/index.css": (request, response) => {
      response.writeHead(200, { "content-type": "text/css;chartset=utf-8" });
      let stream = fs.createReadStream(
        path.join(__dirname, "/views/index.css")
      );
      stream.on("error", function() {
        response.writeHead(500, { "content-type": "text/html;charset=utf-8" });
        response.end("<h1>500 Server Error</h1>");
      });
      stream.pipe(response);
    },
    "/index.js": (request, response) => {
      response.writeHead(200, {
        "content-type": "text/javasvript;chartset=utf-8"
      });
      let stream = fs.createReadStream(
        path.join(__dirname, "/views/index.js")
      );
      stream.on("error", function() {
        response.writeHead(500, { "content-type": "text/html;charset=utf-8" });
        response.end("<h1>500 Server Error</h1>");
      });
      stream.pipe(response);
    },

這樣就正常的加載和執行 css 和 js 了,但是代碼靈活性不夠,重復率太高.

靜態資源服務器

區分路由

...
if (pathname !== "/favicon.ico") {
  if (path.extname(pathname) === "") {
    router(pathname)(request, response);
  } else {
    assets(pathname)(request, response);
  }
}
...

添加靜態資源處理

function assets(p) {
  let ext = path.extname(p);
  ext = ext ? ext.slice(1) : "unknown";
  let contentType = getMime(ext);
  contentType += ";charset=utf-8";
  let filePath;

  if (/image/.test(contentType)) {
    filePath = path.join(static_path, p);
  } else {
    filePath = path.join(public_path, p);
  }

  return async function(request, response) {
    try {
      let stats = await stat(filePath);
      if (stats && stats.isFile()) {
        readFile(response, filePath, contentType);
      }
    } catch (err) {
      console.log(err);
    }
  };
}

我們需要根據文件類型做相應處理

對不同的文件進行不同的響應頭處理

module.exports = {
  getMime: function(ext) {
    let mime = {
      css: "text/css",
      gif: "image/gif",
      html: "text/html",
      ico: "image/x-icon",
      jpeg: "image/jpeg",
      jpg: "image/jpeg",
      js: "text/javascript",
      json: "application/json",
      pdf: "application/pdf",
      png: "image/png",
      svg: "image/svg+xml",
      swf: "application/x-shockwave-flash",
      tiff: "image/tiff",
      txt: "text/plain",
      wav: "audio/x-wav",
      wma: "audio/x-ms-wma",
      wmv: "video/x-ms-wmv",
      xml: "text/xml"
    };
    return mime[ext] || "text/plain";
  }
};

加載相應的靜態文件

function readFile(response, filePath, contentType) {
  response.writeHead(200, { "content-type": contentType });
  let stream = fs.createReadStream(filePath);
  stream.on("error", function() {
    response.writeHead(500, { "content-type": contentType });
    response.end("<h1>500 Server Error</h1>");
  });
  stream.pipe(response);
}

index.js

window.onload = function() {
  let path =
    "http://127.0.0.1:9527/mrw/%E5%B0%8F%E6%B2%AB%E7%90%B3%E3%80%8A%E8%8B%8F%E6%A2%85%E5%B2%9B%E6%97%85%E6%8B%8D%E5%86%99%E7%9C%9F%E3%80%8B%20[%E8%8A%B1%E3%81%AE%E9%A2%9CHuaYan]%20Vol.057%20%E5%86%99%E7%9C%9F%E9%9B%86/%E5%B0%8F%E6%B2%AB%E7%90%B3%E3%80%8A%E8%8B%8F%E6%A2%85%E5%B2%9B%E6%97%85%E6%8B%8D%E5%86%99%E7%9C%9F%E3%80%8B%20[%E8%8A%B1%E3%81%AE%E9%A2%9CHuaYan]%20Vol.057%20%E5%86%99%E7%9C%9F%E9%9B%86_image";

  let suffix = ".jpg";
  let content = document.createElement("div");
  let body = document.getElementsByTagName("body")[0];
  content.setAttribute("class", "content");

  for (let i = 0; i < 56; i++) {
    let item = document.createElement("img");
    item.setAttribute("src", `${path}${i}${suffix}`);
    content.appendChild(item);
  }
  body.appendChild(content);
};

技術分享圖片

當然,正常的寫真集不是這樣做的,而是通過數據庫存儲硬盤路徑存放地址,然後返回給前端 url+path 的形式,路徑也不會這麽長.這裏只是處理靜態文件.

Docs

  • 常見的 MIME 類型
  • fs 模塊 -- JavaScript 標準參考教程(alpha)
  • 用原生 Node 實現一個靜態 web 服務器

    聲明:僅供學習,不可用於商業用途

[Nodejs] node實現靜態文件服務器