准备工作:
准备好一个类似图片中这样的材料
1. 详细步骤
创建 http 服务
// app.js const http = require('http'); // 加载http服务模块 http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'}); res.end(); // 结束响应 }).listen(3000); // 设置端口号 console.log('Server running at http://127.0.0.1:3000/');
获取 URL
// 我们要获取类似这样的url,来展示对应的内容 http://localhost:3000/index.html let pathName = req.url; console.log(pathName); // /index.html /favicon.ico
我们发现发送了两次请求,而 /favicon.ico 这个请求,需要过滤掉。同时,我们需要对空地址做处理,代码如下:
// app.js const http = require('http'); // 加载http服务模块 http.createServer(function (req, res) { let pathName = req.url; pathName = pathName == '/' ? '/index.html' : pathName; if(pathName != '/favicon.ico'){ res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'}); res.end(); } }).listen(3000); console.log('Server running at http://127.0.0.1:3000/');
读取文件
首先加载 fs 模块,如果请求的页面没有找到,则加载404页面
// app.js const http = require('http'); // 加载http服务模块 const fs = require('fs'); http.createServer(function (req, res) { // http://127.0.0.1:3000/login.html // 1. 获取地址 let pathName = req.url; pathName = pathName == '/' ? '/index.html' : pathName; // 2. 通过fs模块读取文件 if(pathName != '/favicon.ico'){ fs.readFile(`./static${pathName}`,(err,data) => { if(err){ fs.readFile('./static/404.html',(err,data404)=>{ if(err){ console.log('404') }else{ res.writeHead(404, {'Content-Type': 'text/html;charset=utf-8'}); res.end(data404); } }) }else{ res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'}); res.end(data); } }) } }).listen(3000); console.log('Server running at http://127.0.0.1:3000/');
此时,我们已经可以看到效果如下:
设置请求头
因为我们将所有请求的文件表头都设置为 ‘Content-Type’: ‘text/html;charset=utf-8’;
这显然是错误的做法。比如:css 文件 应设置为 ‘text/css’ , js文件 设置为 ‘text/javascript’ 。
我们先创建一个文件夹,将它命名为 module,在该文件夹下创建一个 js 文件 common.js
代码如下:
// common.js const fs = require('fs'); exports.getFileMime = (extName) => { // readFileSync 为 readFile 的同步方法 let data = fs.readFileSync('./data/mime.json'); // 注意:因为该方法在 app.js 引用,所以相对位置应以app.js为基点 let mimeObj = JSON.parse(data.toString()); return mimeObj[extName] }
我们要根据对应的请求的文件后缀名来设置对应的文件格式,因此要引入 path 模块。再用 path.extname() 方法,获取到对应的后缀名。
// app.js const http = require('http'); // 加载http服务模块 const fs = require('fs'); const path = require('path'); const common = require('./moudle/common'); http.createServer(function (req, res) { // http://127.0.0.1:3000/login.html // 1. 获取地址 let pathName = req.url; pathName = pathName == '/' ? '/index.html' : pathName; // 获取后缀名 path.extname(); let extname = path.extname(pathName) console.log(pathName) // 2. 通过fs模块读取文件 if(pathName != '/favicon.ico'){ fs.readFile(`./static${pathName}`,(err,data) => { if(err){ fs.readFile('./static/404.html',(err,data404)=>{ if(err){ console.log('404') }else{ res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'}); res.end(data404); } }) }else{ let mime = common.getFileMime(extname) // 根据对应的后缀名,获取对应的文件格式 res.writeHead(200, {'Content-Type': `${mime};charset="utf-8"`}); res.end(data); } }) } }).listen(3000); console.log('Server running at http://127.0.0.1:3000/');
结果如图所示:
但是,对应的图片并未加载进来。这是因为:这两个文件未加载,原因是请求地址后带参数,无法识别,所以需要再引入 url 模块,使用 url.parse() 方法,将该地址解析为不带参数的地址;
完整代码:
// app.js const http = require('http'); // 加载http服务模块 const fs = require('fs'); const path = require('path'); const url = require('url'); const common = require('./moudle/common'); http.createServer(function (req, res) { // http://127.0.0.1:3000/login.html // 1. 获取地址 let pathName = url.parse(req.url).pathname; pathName = pathName == '/' ? '/index.html' : pathName; // 获取后缀名 path.extname(); let extname = path.extname(pathName) // 2. 通过fs模块读取文件 if(pathName != '/favicon.ico'){ fs.readFile(`./static${pathName}`,(err,data) => { if(err){ fs.readFile('./static/404.html',(err,data404)=>{ if(err){ console.log('404') }else{ res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'}); res.end(data404); } }) }else{ let mime = common.getFileMime(extname) // 根据对应的后缀名,获取对应的文件格式 res.writeHead(200, {'Content-Type': `${mime};charset="utf-8"`}); res.end(data); } }) } }).listen(3000); console.log('Server running at http://127.0.0.1:3000/');
结果如图:
2. 封装静态 WEB 服务器
如上图所示,在 NODEJS 目录下新建 staticApp.js 在 moudle目录下新建 route.js,用于封装静态 web 服务器。
// route.js const fs = require('fs'); const path = require('path'); const url = require('url'); // 私有方法 function getFileMime(extName){ // readFileSync 为 readFile 的同步方法 let data = fs.readFileSync('./data/mime.json'); // 注意:因为该方法在 app.js 引用,所以相对位置应以app.js为基点 let mimeObj = JSON.parse(data.toString()); return mimeObj[extName] } exports.static = (req,res,staticPath) => { // 1. 获取地址 let pathName = url.parse(req.url).pathname; pathName = pathName == '/' ? '/index.html' : pathName; // 获取后缀名 path.extname(); let extname = path.extname(pathName) // 2. 通过fs模块读取文件 if(pathName != '/favicon.ico'){ fs.readFile(`./${staticPath}${pathName}`,(err,data) => { if(err){ fs.readFile('./static/404.html',(err,data404)=>{ if(err){ console.log('404') }else{ res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'}); res.end(data404); } }) }else{ let mime = getFileMime(extname) // 根据对应的后缀名,获取对应的文件格式 res.writeHead(200, {'Content-Type': `${mime};charset="utf-8"`}); res.end(data); } }) } }
// staticApp.js const http = require('http'); // 加载http服务模块 const routes = require('./moudle/routes') http.createServer(function (req, res) { routes.static(req,res,'static') }).listen(8000); console.log('Server running at http://127.0.0.1:8000/');
结果如图: