详解Nodejs之静态资源处理

前言

刚开始用Nodejs写简单的web服务器的时候,总是感觉少了点什么。

原来,我一直是在页面上输出什么Hello World!啊, It Works.之类的了。还确实没有处理关于CSS, JS这些引用的静态相关的资源。

一开始觉得处理这些东西应该会非常的easy,结果发现不仅仅是这么回事。途中也遇到了一些人们经常可能会犯的想当然的错误。于是我就决定好好的记录一下关于Nodejs中对于静态资源的处理。

着眼于问题

重现问题

先来展示一下目录结构吧。

E:\CODE\NODEJS\LEARN\WEB\EXPRESS-STATIC
│ server.js
│
├─html
│   index.html
│
└─public
  ├─css
  │   index.css
  │
  ├─imgs
  │   1.gif
  │
  └─js
      index.js

这样一个web项目的骨架就算是搭建好了。下面简单的使用nodejs的http模块实现一个web服务器。目标就是显示index.html

index.html

<html>
  <head>
    <meta charset="UTF-8">
    <title>My Index Page</title>
    <link rel="stylesheet" href="/public/css/index.css" rel="external nofollow" >
  </head>
  <body>
    <h1>It Works.</h1>
    <hr>
    <img src="/public/imgs/1.gif" />
  </body>
</html>

index.css

* {
  padding: 0px;
  margin: 0px;
}

h1 {
  color: yellowgreen;
}

body {
  background-color: #2C001E;
}

server.js

var http = require('http');
var fs = require('fs');

function handle_request(req, res) {

  // 客户端对服务器的请求,说白了就是对相关文件内容的请求。
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end(get_file_content(__dirname + '\\' + 'html' + '\\' + 'index.html'));
}

function get_file_content(filepath) {
  return fs.readFileSync(filepath);
}

var server = http.createServer(handle_request);
server.listen(8080);

代码中用到了一个名为__dirname的变量,其值就是当前运行文件的绝对路径。通过它,我们可以组装出我们想要获取的文件的全路径。

运行代码,开启服务器。

node server.js

发现问题

然后我们打开浏览器,会发现这样的景象。

没有任何效果的页面

不仅是CSS样式没显示出来,就连图片也同样没有正确显示。

然后我们打开浏览器控制台,会发现客户端向服务器发送了3次请求,分别是:

客户端请求内容

  1. localhost: HTML代码页
  2. index.css: 样式文件
  3. 1.gif: 图片文件

之所以我们没能看到具体的效果,就是因为服务器没有正确返回相关的内容啊。这样一想,一下子就恍然大悟了。所以这颗Silver Bullet就是

针对每一个不同的资源请求,正确的返回相关的内容。

解决问题

我的思路:

  1. 剖析request请求地址。分割出文件名,后缀名。
  2. 根据后缀补全相关文件在文件系统中的全路径。
  3. 根据全路径读取内容,返回给客户端。

server.js

然后简单的修改了一下server.js,当然这里也只是简单的做下示意,生产代码可千万不要这么写。

var http = require('http');
var fs = require('fs');

function handle_request(req, res) {

  // 不管是什么请求,对文件的请求的话,应该是针对后缀名进行内容读取发放。
  var suffix = req.url.substr(req.url.length - 4, req.url.length);
  var realpath = __dirname + '\\' + 'public' + '\\';
  var filename = req.url.substr(req.url.length - 9);
  if (suffix === '.css') {
    res.writeHead(200, { 'Content-Type': 'text/css' });
    res.end(get_file_content(realpath + '\\css\\' + filename));
  } else if (suffix === '.gif') {
    res.writeHead(200, {'Content-Type': 'image/gif'});
    res.end(get_file_content(realpath+'\\imgs\\1.gif'));
  } else {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(get_file_content(__dirname + '\\' + 'html' + '\\' + 'index.html'));
  }
}

function get_file_content(filepath) {
  return fs.readFileSync(filepath);
}

var server = http.createServer(handle_request);
server.listen(8080);

然后重启服务器。

node server.js

再次访问浏览器

http://localhost:8080

如下:

因为没有录屏,所以没体现出GIF图的效果,不过关于静态资源已经足够显示了。

express

还有一个比较好用的web框架,express,其对于静态资源的支持更加方便。属于一个更加高层的封装。

核心

通过express对象的app.use(express.static(folder_path))方法就可以了。方法的参数指定为相关的静态资源文件夹路径即可。

server-express.js

/**
 * 使用express来实现对于静态资源的控制。
 */
let express = require('express');
let fs = require('fs');
let path = require('path');

var app = express();

app.use(express.static(path.join(__dirname, './public')));

app.all('/', function(req, res){
  console.log("=======================================");
  console.log("请求路径:"+req.url);
  var filename = req.url.split('/')[req.url.split('/').length-1];
  var suffix = req.url.split('.')[req.url.split('.').length-1];
  console.log("文件名:", filename);
  if(req.url==='/'){
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(get_file_content(path.join(__dirname, 'html', 'index.html')));
  }else if(suffix==='css'){
    res.writeHead(200, {'Content-Type': 'text/css'});
    res.end(get_file_content(path.join(__dirname, 'public', 'css', filename)));
  }else if(suffix in ['gif', 'jpeg', 'jpg', 'png']) {
    res.writeHead(200, {'Content-Type': 'image/'+suffix});
    res.end(get_file_content(path.join(__dirname, 'public', 'images', filename)));
  }
});

function get_file_content(filepath){
  return fs.readFileSync(filepath);
}

app.listen(8080);

index.html

因为刚才使用了静态资源控制,也就是说我们可以简化HTML页面中对于静态资源的路径拼写。比如:

原来在HTML页面中要这么写:

<img src='/public/images/1.gif' />

现在只需要这么写了:

<img src='/images/1.gif' />

看起来就是少了个 /public, 但是实际上通过这一点就可以表明express 其实帮我们省去了很多枯燥的工作内容。

然后打开浏览器就可以看到具体的静态资源内容了。

那么对于不同的图片类型的支持程度如何呢?

下面修改一下HTML页面:

<html>
  <head>
    <meta charset="UTF-8">
    <title>My Index Page</title>
    <link rel="stylesheet" href="/css/index.css" rel="external nofollow" >
  </head>
  <body>
    <h1>It Works.</h1>
    <hr>
    <img src="/images/1.gif" /><br>
    <img src="/images/2.jpg" alt=""><br>
    <img src="/images/3.png" alt=""><br>
  </body>
</html>

打开浏览器查看对于gif, png, jpg的支持如何?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Nodejs回调加超时限制两种实现方法

    Nodejs回调加超时限制两种实现方法 Nodejs下的IO操作都是异步的,有时候异步请求返回太慢,不想无限等待回调怎么办呢?我们可以给回调函数加一个超时限制,到一定时间还没有回调就表示失败,继续后面的步骤. 方案1:用async的parallel实现 在这里我用到了async的parallel方法,parallel可以让若干个异步回调的方法并行执行,正常情况下,所有回调函数都完成后会汇集到parallel最终的回调函数里,但是有一种例外,如果其中一个步骤有错误抛出并直接调用parallel最终

  • nodejs socket实现的服务端和客户端功能示例

    本文实例讲述了nodejs socket实现的服务端和客户端功能.分享给大家供大家参考,具体如下: 使用node.js的net模块能很快的开发出基于TCP的服务端和客户端.直接贴代码. server.js /** * Created with JetBrains WebStorm. * User: Administrator * Date: 12-10-26 * Time: 下午3:44 * To change this template use File | Settings | File T

  • 深入理解Nodejs Global 模块

    浏览器上有自己的全局对象 window,同理, nodejs 下也有自己的全局对象 global,并且在各个模块下 都可以直接访问 global 对象. 在 nodejs 中,除了可以直接使用 V8 JavaScript 引擎中所支持的原生 JavaScript 的函数和对象外,它还追加了一些其他的函数和对象(比如:Buffer 对象.require 函数等). Buffer 对象: 用于处理二进制数据 module 对象: 用于访问当前模块的信息 process 对象: 用于访问进程信息 co

  • 详解nodeJS之二进制buffer对象

    前面的话 在ES6引入TypedArray之前,JavaScript语言没有读取或操作二进制数据流的机制.Buffer类被引入作为Nodejs的API的一部分,使其可以在TCP流和文件系统操作等场景中处理二进制数据流.现在TypedArray已经被添加进ES6中,Buffer类以一种更优与更适合Node.js用例的方式实现了Uint8Array.本文将详细介绍buffer对象 概述 由于应用场景不同,在Node中,应用需要处理网络协议.操作数据库.处理图片.接收上传文件等,在网络流和文件的操作中

  • mongoDB 多重数组查询(AngularJS绑定显示 nodejs)

    核心代码: js代码 var Lesson = Schema({ lessonName: String, intr: String, creTime: Date, sort: String, //分类 imgUrl: String, //封面地址 price: Number, teacher: String,//教师 subTitle:[{ lNo: Number, subLName: String, src: String, filtered: {type: Boolean, default:

  • 详解nodeJS之路径PATH模块

    前面的话 path模块包含一系列处理和转换文件路径的工具集,通过 require('path') 可用来访问这个模块.本文将详细介绍path模块 路径组成 [path.dirname(p)] 返回路径p所在的目录 var path = require('path'); console.log(path.dirname('/foo/bar/baz/asdf/a.txt')); // /foo/bar/baz/asdf console.log(path.dirname('/foo/bar/baz/a

  • 详解Nodejs之静态资源处理

    前言 刚开始用Nodejs写简单的web服务器的时候,总是感觉少了点什么. 原来,我一直是在页面上输出什么Hello World!啊, It Works.之类的了.还确实没有处理关于CSS, JS这些引用的静态相关的资源. 一开始觉得处理这些东西应该会非常的easy,结果发现不仅仅是这么回事.途中也遇到了一些人们经常可能会犯的想当然的错误.于是我就决定好好的记录一下关于Nodejs中对于静态资源的处理. 着眼于问题 重现问题 先来展示一下目录结构吧. E:\CODE\NODEJS\LEARN\W

  • 详解nodejs内置模块

    概述 nodejs内置模块指的是除默认提供的语法之外,提供的美容,无需下载,直接引入,引入只写名称即可. nodejs内置模块: 1.path模块  用于处理文件路径. path.normalize(路径解析,得到规范路径): path.join(路径合并): path.resolve(获取绝对路径): path.relative(获取相对路径). ...... 2.until模块  弥补js功能不足,新增API. util.format(格式化输出字符串); util.isArray(检查是否

  • 详解NodeJS模块化

    目录 一.前言 二.正文 2.1.什么是模块 2.2.Resolving 2.3.require.resolve 2.4.模块间的父子依赖关系 2.5.exports, module.exports 2.6.模块循环依赖 2.7..json和.node 2.8.Wrapping 2.9.Cache 三.总结 一.前言 我们知道,Node.js是基于CommonJS规范进行模块化管理的,模块化是面对复杂的业务场景不可或缺的工具,或许你经常使用它,但却从没有系统的了解过,所以今天我们来聊一聊Node

  • 详解C#编程获取资源文件中图片的方法

    详解C#编程获取资源文件中图片的方法 本文主要介绍C#编程获取资源文件中图片的方法,涉及C#针对项目中资源文件操作的相关技巧,以供借鉴参考.具体内容如下: 例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Drawing; namespace CL { public class RES { /

  • 详解nodejs中的异步迭代器

    前言 从 Node.jsv10.0.0 开始,异步迭代器就出现中了,最近它们在社区中的吸引力越来越大.在本文中,我们将讨论异步迭代器的作用,还将解决它们可能用于什么目的的问题. 什么是异步迭代器 那么什么是异步迭代器?它们实际上是以前可用的迭代器的异步版本.当我们不知道迭代的值和最终状态时,可以使用异步迭代器,最终我们得到可以解决{value:any,done:boolean}对象的 promise.我们还获得了 for-await-of 循环,以帮助我们循环异步迭代器.就像 for-of 循环

  • 详解nodejs通过响应回写的方式渲染页面资源

    我们一般通过node框架提供的api操作页面渲染,如何利用原始回写的方式来实现同样的功能呢 下面是通过node 提供的异步地读取一个文件的全部内容api readFile进行操作,代码如下: html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content=&quo

  • 详解Nodejs内存治理

    s运行的宿主环境不同,相应的对内存治理的要求也不一样,当宿主环境是浏览器时,由于网页的运行时间短,且只运行在用户的机器上(相当于分布式),即使内存使用过多或者存在一定的内存泄漏,也并不会对终端用户产生太大的影响.当宿主环境编程服务器(Node)时,情况就大不相同了,本身代码运行在固定的几台机器(集中式)上,而且运行的时间是长时间运行,一旦内存治理不好出现了内存膨胀甚至是内存泄漏的情况的话,就会出现服务器端响应时间变长甚至是服务crash的情况. Nodejs是基于V8构建的,所以在Node中使用

  • 详解Nodejs get获取远程服务器接口数据

    本文实例为大家分享了Nodejs get获取远程服务器接口数据的具体代码,供大家参考,具体内容如下 1.GET模块:_get.js /** * Created by jinx on 7/7/17. */ var http = require('http'); module.exports = { /** * 测试获取所有的区域 * / locations: function (cb) { http.get('http://wx.xx.com/locations', function (res)

  • 详解nodejs的express如何自动生成项目框架

    本文主要介绍了nodejs的express如何自动生成项目框架,这里整理了详细的代码,有需要的小伙伴可以参考下. nodejs版本为:4.X,express版本为4.X 1.全局安装2个模块 express.express-generator 在命令行输入: npm install -g express npm install -g express-generator 如果模块下载很慢可以在后面 空格加上淘宝的镜像 --registry=https://registry.npm.taobao.o

  • 详解nodeJs文件系统(fs)与流(stream)

    一.简介 本文将介绍node.js文件系统(fs)和流(stream)的一些API已经参数使用情况. 二.目录 文件系统将介绍以下方法: 1.fs.readFile 2.fs.writeFile 3.fs.open 4.fs.read 5.fs.stat 6.fs.close 7.fs.mkdir 8.fs.rmdir 9.fs.readdir 10.fs.unlink stream流的四种类型readable,writable,duplex,transform以及stream对象的事件. 三.

随机推荐