day21JS-npm中的部分插件使用方法

1. 静态资源目录

静态资源目录就是访问服务器的某些路劲时候,服务器可以吐出一个写好的指定页面。

实现思路:

1、先判断要找的路径是否是文件,如果是文件,就加载发给对方。

2、如果是文件夹,找到这个文件夹所在路径中有没有index.html,如果有加载发送。

3、如果文件夹,并没有index.html,加载404发送。

案例:

  1. 创建一个api的文件夹,打开集成终端执行npm init -y 命令得到一个package.json文件,编写该文件。
javascript 复制代码
{
  "name": "api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon PORT=4000"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^3.1.4"
  },
  "dependencies": {
    "cheerio": "^1.0.0",
    "jsonwebtoken": "^9.0.2",
    "mime": "^3.0.0",
    "node-xlsx": "^0.24.0"
  }
}
  1. 创建入口文件index.js ,

3.创建staticPublic.js文件,编写该文件。在集成终端中执行npm start 命令启动命令。

javascript 复制代码
const http = require("http");
const path = require("path");
const mime = require("mime");
// 创建一个服务
http.createServer(async function (req, res) {
    // 获取到响应对象的路劲
    let url = req.url;
    // 加载
    let [result, mimeType] = await getFile(url)
    //编写请求头
    res.writeHead(200, {
        // 如果是文本文件就解析它,如果不是文本文件就直接返回
        "Content-Type": /text/.test(mimeType) ? mimeType + ";charset=utf-8" : mimeType
    })
    res.end(result);
}).listen(process.env.PORT)

// 获取文件函数
async function getFile(url) {
    // 获取当前文件的上一级路劲并拼接上public
    const paths = path.join(path.resolve(), "public", url);
    // 使用fsp.stat()方法获取到路劲最后面的路劲判断是不是文件
    const stat = await fsp.stat(paths).catch(e => { });
    // 不是文件的情况,则返回404页面
    if (!stat) {
        return await getFile("/404.html");
    }
    // 是文件的情况
    if (stat.isFile()) {
        // 使用mime.getType()方法判断文件类型
        return [await fsp.readFile(paths), mime.getType(paths)];

        // 是文件夹的情况
    } else if (stat.isDirectory()) {
        // 获取到当前文件的上一级路劲并拼接上index.html页面
        return await getFile(path.join(url, "./index.html"))
    }
}

4.在入口文件index.js 中导入staticPublic.js文件。

javascript 复制代码
require("./staticPublic")
  1. 创建一个public的文件夹,在创建一个image文件夹存放几张图片。

  2. 在public的文件夹下创建一个index.html文件和一个404.html文件,并编写该文件。

index.html文件:

html 复制代码
<body>
    <a href="#">超链接</a>
    <img src="/img/img_12.JPG">
</body>

404.html文件:

html 复制代码
<body>
    <h1>404</h1>
</body>

2. 爬虫

爬虫:获取一个网页中全部的文件和内容。一般用于静态页面。

爬虫使用的插件:cheerio是模仿jQuery方式实现的一个第三方爬虫解析插件,可以将文本像html一样通过选择器和筛选器将数据分离。

方法:

cheerio.load(数据结果) :加载数据。

$("标签名/类名/id名").each((index, item) => { ...} : 遍历。

$(标签名).attr("属性名"); :获取标签的某个属性。

  1. 在api的文件夹下创建一个reptile.js文件,并编写该文件。
javascript 复制代码
// 引入https模块
const https = require("https");
// 引入爬虫插件
const cheerio = require("cheerio");
// querystring解析模块
const querystring = require("querystring");
// 引入文件模块
const fsp = require("fs/promises")
const path = require("path");
// 获取到网址
https.get("https://news.163.com/", async function (respone) {
    let list = [];
    // 调用该函数获取到网址上的数据
    let result = await getData(respone)
    // 使用cheerio.load()解析数据
    let $ = cheerio.load(result)
    // 使用元素选择器获取到所有的img标签,然后遍历
    // index:元素索引, item:元素
    $("img").each((index, item) => {
        // 获取到img标签的src属性
        let src = $(item).attr("src");
        // 没有src属性的情况
        if (!src) {
            // 使用querystring.parse()解析获取到data-original属性
            src = querystring.parse($(item).attr("data-original").split("?")[1]).url;
        }
        list.push(src);
    })
    for (var i = 0; i < list.length; i++) {
        // 如果没有https开头就要添加一个https
        if (!/https?/.test(list[i])) list[i] = "https:" + list[i];
        let result = await getFile(list[i]);
        if (!result) continue;
        let fileName = list[i].split("/").pop();
        await fsp.writeFile(path.join(path.resolve(), "./public/img", fileName), result)
    }
})

// 获取数据的函数
function getData(req) {
    return new Promise(function (resolve, reject) {
        let data = ""
        req.on("data", _chunk => data += _chunk);
        req.on("end", () => resolve(data))
    })
}

// 获取文件数据都函数
function getFile(url) {
    return new Promise(function (resolve, reject) {
        https.get(url, async function (respone) {
            let result = await getImageData(respone);
            resolve(result);
        })
    })
}

// 获取图片数据的函数
function getImageData(req) {
    return new Promise(function (resolve, reject) {
        let data = Buffer.alloc(0);
        req.on("data", _chunk => {
            data = Buffer.concat([data, _chunk], data.length + _chunk.length);
        });
        req.on("end", () => resolve(data))
    })
}

2.在入口文件index.js 中导入reptile.js文件。

javascript 复制代码
require("./reptile");

3. Excel表格解析

Excel表格解析需要先下一个第三方模块**node-xlsx,**这里完成了一个excel表格筛选重建的内容然后创建一个新的表格文件。

  1. 在api的文件夹下创建一个excels.js文件,并编写该文件。
javascript 复制代码
const fsp = require("fs/promises");
const xlsx = require("node-xlsx");
const path = require("path");
init();
async function init() {
    // 读取文件内容
    let result = await fsp.readFile(path.join(path.resolve(), "./public/excel/cjd.xlsx"))
    // 使用xlsx.parse()解析数据,获得一个数组对象
    let data = xlsx.parse(result);
    // 把总分不及格的人筛选出来
    let data1 = data[0].data.filter((item, index) => {
        // 不是元素第4项直接跳出
        if (index < 4) return true;
        return Number(item[item.length - 1]) < 60;
    })
    // 创建一张excels表格
    let buffer = xlsx.build([{ name: "不及格的成绩单", data: data1 }]);
    // 把筛选出来数据写入表格
    await fsp.writeFile(path.join(path.resolve(), "./public/excel/a.xlsx"), buffer)
}
  1. 在入口文件index.js 中导入excels.js文件。
javascript 复制代码
require("./excels");

4. Crypto原生加密

引入语法:const crypto = require("crypto");

方法:

crypto.createHmac(加密key, 要加密的字符串) .update("更新的密码").digest("指定字符集")

javascript 复制代码
const crypto = require("crypto");
var str = 'abcdef';
var hash = crypto.createHmac("sha256", str).update("123456").digest("dex")
console.log(hash);

5. bcrypt 第三方加密

下载命令:npm i bcrypt -S

加密:

javascript 复制代码
 bcrypt.hash(password,10,function(err,encryted){
            console.log(encryted);
 })

验证:

javascript 复制代码
 bcrypt.compare(pass,hash,function(err,bool){
            console.log(bool);
        })

6. jsonwebtoken加密

下载命令:npm i jsonwebtoken

引入语法:const jsonwebtoken = require("jsonwebtoken");

方法:

jsonwebtoken.sign(要加密的字符串, 加密key):加密

jsonwebtoken.verify(要解密密的字符串, 加密key):解密

对称加密 :加密的秘钥和解密的秘钥是完全相同的

非对称加密 :加密的秘钥和解密的秘钥是不相同的 。jsonwebtoken使用借助于openssl密钥的生成。私钥加密,公钥解密。

openssl下载地址:Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions

打开openssl命令行******:openssl**

生成一个2048位的私钥:genrsa -out rsa_private_key.pem 2048

根私钥生成公钥:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

加密:

javascript 复制代码
const jsonwebtoken = require("jsonwebtoken");
let key = "xietian";

let str = "abcdef";
let hash = jsonwebtoken.sign(str, key);
console.log(hash);

解密:

javascript 复制代码
const jsonwebtoken = require("jsonwebtoken");
let key = "xietian";

let hash1 = "eyJhbGciOiJIUzI1NiJ9.YWJjZGVm.pazQAwUB0OAO-xlF6D0sV1r-lQCPGQcGwvUWV20fiuE";
let str1 = jsonwebtoken.verify(hash1, key);
console.log(str1);

案例1:

javascript 复制代码
const jsonwebtoken = require("jsonwebtoken");
// 加密
var data = { name: "kwj", age: 20 };
let hash = jsonwebtoken.sign(data, "123456");
console.log(hash);
console.log("--------------------------");
// 解密
var data1 = { name: "xietian", age: 20 };
let hash1 = jsonwebtoken.verify(hash, "123456")
console.log(hash1);

案例2:jsonwebtoken的对称解密

javascript 复制代码
// 对称加密  秘钥 加密的秘钥和解密的秘钥是完全相同的
// 可以多次加密解密
const jsonwebtoken = require("jsonwebtoken");
// 加密
var data = { a: 1, b: 2 };
var hash = jsonwebtoken.sign(data, "123456");
var hash1 = jsonwebtoken.sign(hash, "123456");
console.log(hash1);
console.log("----------------------------------");
// 解密
var hash2 = jsonwebtoken.verify(hash1, "123456");
var data1 = jsonwebtoken.verify(hash2, "123456");
console.log(data1);

案例3:jsonwebtoken的非对称解密

javascript 复制代码
const jsonwebtoken = require("jsonwebtoken");
const fsp = require("fs/promises");
const path = require("path")
// 非对称加密
init();
async function init() {
    var data = { name: "xietian", age: 20 };
    var privateKey = await fsp.readFile(path.resolve("./rsa_private_key.pem"));
    var hash = jsonwebtoken.sign(data, privateKey, { algorithm: "RS256" })
    var publicKey = await fsp.readFile(path.resolve("./rsa_public_key.pem"));
    var data1 = jsonwebtoken.verify(hash, publicKey);
    console.log(data1);
}

7. cors跨域

下载命令:npm i cors -S

使用方法(固定写法) :app.use(cors())

8. 客户端版socket

连接分为长连接和短连接(客户端给服务端发消息,服务端返回消息,然后连接就断了)。

socket是一种长连接,因此需要保障每一个连接过来的客户端都被存储引用。

readline是读取终端的行消息。

引入模块:

const net = require('net');

服务端创建服务:

const server = new net.createServer();

客户端创建socket服务:

var socket = new net.Socket();

引入模块:

const readline = require("readline");

实现案例:

服务端:

  1. 创建一个socketServer1文件夹,在该文件夹下打开集成终端执行npm init -y 命令初始化得到package.json文件,编写该文件。
javascript 复制代码
{
  "name": "socketserver1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon PORT=4000 "
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^3.1.4"
  }
}
  1. 在集成终端执行 npm i 和npm start命令。

  2. 新建入口文件index.js,编写代码。

javascript 复制代码
// 引入net模块
const net = require("net");
// 创建服务器(服务端)
const server = net.createServer();
// n表示连接成功的次数
let n = 0;
// 连接上的client集合
let list = {};
// server.on()方法是侦听connection事件的连接情况
server.on("connection", connnectionHandler);
// server.listen()开启端口号
server.listen(process.env.PORT);
// 侦听connection事件的函数(参数:客户端)
function connnectionHandler(client) {
    n++;
    // 相当于给进来的client取名字
    client.name = n;
    // client存入list
    list[n] = client;
    // console.log(Object.keys(list).length);
    // 侦听客服端error出错事件的函数
    client.on("error", () => errorHandler(client));
    // 侦听客服端close关闭事件的函数
    client.on("close", () => closeHandler(client));
    // 侦听服务器发送数据给客户端的函数
    client.on("data", (msg) => getMsgHandler(msg, client))
}
// 侦听客服端发送数据的函数
function getMsgHandler(msg, client) {
    console.log(msg + "");
    for (var key in list) {
        list[key].write(msg + "");
    }
}

// 侦听客服端error出错事件的函数
function errorHandler(client) {
    console.log(client.name + " error");
    // 关闭出错的client的连接
    client.end();
}

// 侦听客服端close关闭事件的函数
function closeHandler(client) {
    console.log(client.name + "关闭下线了");
    // 关闭client的连接
    client.end();
    // 从集合中删除
    delete list[client.name];
}

客服端:

  1. 创建一个socketClient1文件夹,在该文件夹下打开集成终端执行npm init -y 命令初始化得到package.json文件,编写该文件。
javascript 复制代码
{
  "name": "socketclient1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  1. 新建入口文件index.js,编写代码。
javascript 复制代码
// 也要引入net模块
const net = require("net");
// 读取终端行消息模块
const readline = require("readline");
// 这个代码让我们的命令行变为输入端和输出端
const order = readline.Interface({
    // 这里是输入端
    input: process.stdin,
    // 这里是输出端
    output: process.stdout
})

let socket;
init();
// 初始化函数
function init() {
    // 客户端创建socket服务
    socket = new net.Socket();
    // 连接服务端(参数:4000的端口号,参数:域名或id地址,参数:连接成功的回调函数)
    socket.connect(4000, "localhost", () => {
        // 当连接上服务端执行这个函数
        // 发信息的方法一:
        // socket.write()方法是直接发消息给服务端
        // socket.write("你好");
        // 发信息的方法二:
        // order.question("输入:", (msg) => {
        //     // 发送的消息
        // })
    })
    // 侦听服务端发送回来的数据
    socket.on("data", (msg) => msgHandler(msg));
    inputShow();
}

function msgHandler(msg) {
    console.log(msg + "");
}

// 使用readline模块的方法发送消息
function inputShow() {
    order.question("输入:", (msg) => {
        socket.write("谢天说:" + msg);
        inputShow();
    })
}
相关推荐
德莱厄斯18 分钟前
三行代码完成国际化适配,妙~啊~
前端·javascript·babel
2301_7891695420 分钟前
JSON.parse(JSON.stringify())深拷贝不会复制函数
开发语言·前端·javascript
程序员XC24 分钟前
前端性能优化的思考过程
前端·javascript·面试
皮皮虾我们跑1 小时前
web—HTML
前端·html
JosieBook1 小时前
【前端】如何在HTML中调用CSS和JavaScript(完整指南)
前端·css·html
唐诗1 小时前
这位同学来说一说 vue3 的组件通信
前端
积跬步,慕至千里1 小时前
pyspark RDD相关常用函数使用案例
前端·javascript·ajax
星星不打輰2 小时前
Vue脚手架基础
前端·javascript·vue.js
好_快2 小时前
Lodash源码阅读-compact
前端·javascript·源码阅读