目 录CONTENT

文章目录

NodeJS常用插件

Administrator
2020-07-24 / 0 评论 / 0 点赞 / 7853 阅读 / 15613 字

NodeJS常用模块

在NodeJS的开发过程当中,经常会使用一些第三方的插件,现在我们将三个将用的插件讲解一下

NodeJS操作EXCEL插件

这个插件的名子叫node-xlsx,可以直接在npm上面去安装

$ npm install node-xlsx --save

读取EXCEL文件

主要使用的方法就是 parse()方法,将一个excel文件转到成JS对象

const xlsx=require("node-xlsx");
const path=require("path");
let obj = xlsx.parse(path.join(__dirname,"stuinfo.xlsx"));

通过上面的方法,我们可以得到obj对象,它就是读取的excel结果

读取的obj结果

[ { name: 'Sheet1', data: [ [Array], [Array], [Array] ] },
  { name: 'Sheet2', data: [] } ]

它得到的是一个数组,excel文件里面的每一个工作表都是一个对象, name代表这个工作表的名称,而data代表表格里面的数据

data数据结果

[ [ 'sid', 'sname', 'ssex', 'sbirthday', 'snation', 'cid', 'saddr' ],
  [ 2005010101,
    '苏俊丹       ',
    '女         ',
    '1/12/1987',
    '汉族',
    20050101,
    '河南商丘' ],
  [ 2005010102,
    '张小苗       ',
    '男         ',
    '5/15/1985',
    '汉族',
    20050101,
    '河南洛阳' ] ]

通过上面的结果,我们可以看出,data是一个二维数组,这个数组里面的第一个元素代表了当前表格里面的表头,后面的代表表格里面的数据

读取EXCEL导入到数据库

const xlsx = require("node-xlsx");
const DBUtil=require("./utils/DBUtil.js");
//现在我们应该去读取当前文件夹下面的stuinfo.xlsx这个文件了
//__dirname是NodeJS的内置变量,代表当前运行的文件所在的文件夹
// console.log(__dirname);
//我们在当前文件夹下面去读取stuinfo.xlsx文件

async function readExcel() {
    const path = require("path"); //NodeJS系统内置的包,用于看得NodeJS下面的路径问题
    //join()是路径拼接
    let excelPath = path.join(__dirname, "stuinfo.xlsx"); //得到了这个excel的路径
    let obj = xlsx.parse(excelPath);
    console.log(obj);
    //第一件事情,先拿到表头
    let thead = obj[0].data[0];
    console.log(obj[0].data);
    //第二步:根据表头创建数据表
    let ddlStr = `create table if not exists stuinfo (
    ${thead.map(item => {
        return item + " varchar(200) ";
    }).join(",")}
) engine=innodb default charset=utf8`;
    //执行上面的DDLSQL语句
    try {
        await DBUtil.executeSql(ddlStr);
        //表格创建完成,循环读取数据,向数据库插入内容
        for(let i=1;i<obj[0].data.length;i++){
            let strSql=`insert into stuinfo values (${new Array(thead.length).fill("?").toString()})`;
            await DBUtil.executeSql(strSql,obj[0].data[i]);
        }
    } catch (err) {
        console.log(err);
    }
    
}

readExcel();
  • __dirname 代表当前文件所执行的文件夹路径
  • path 是NodeJS自带的模块,里面的join()方法用来拼接路径
  • DBUtil这个对象请查看之前的笔记,里面用Promise实现了异步编程
  • asyncawaitPromise进行结合,异步转同步的代码,请参考上一节笔记

数据库数据导出为EXCEL

这个功能在系统里面经常使用,我们会经常需要将查询的表格结果导出为excel文件,这个时候主要使用的是node-xlsx 里面的build() 方法,要注意它接收的参数格式

/**
 * 导出
 */
const xlsx=require("node-xlsx");
const DBUtil=require("./utils/DBUtil.js");
const path=require("path");   //NodeJS内置模块,用于处理路径
const fs=require("fs");       //NodeJS用于处理文件模块 fs  FileSystem/FileStream

async function dbToExcel() {
    let strSql = "select * from stuinfo";
    let result = await DBUtil.executeSql(strSql); //应该是一个数组
    if(result.length>0){
        let excelData=[];
        excelData.push(Object.keys(result[0]));
        result.forEach(item=>{
            let values = Object.values(item);
            excelData.push(values);
        });
        
        //生成好的excel缓存文件,现在在内存里面,我们要把它写入到硬盘里面去
        let buffer = xlsx.build([
            {
                name:"stuinfo",
                data:excelData
            }
        ]);
        //writeFileSync将缓存写入到电脑的某个文件
        fs.writeFileSync(path.join(__dirname,"abc.xlsx"),buffer);
    }

}
dbToExcel();

上面的excelData就是我们要生成的数据,它是一个二维数组,里面的第一个元素是表头,后面的代表表的数据。所以要注意将SQL的查询结果result转换成excel 所需要的数据


导出为EXCEL这个结果,我们在后期会经常使用,所以我们必然要把它封装成一个就去

封装EXCEL的导出操作

/**
 * @description EXCEL操作工具类,涉及到EXCEL导入与导出
 */

 const xlsx=require("node-xlsx");
 const fs=require("fs");

 /**
  * @class ExcelUtil 
  * @requires node-xlsx
  */
 class ExcelUtil{
     /**
      * @name resultToExcel  数据库结果result转换为EXCEL
      * @param {Array} result 要导出的数组数据 
      * @param {string} excelPath 要保存的EXCEL路径
      */
    static resultToExcel(result,excelPath){
        if(!Array.isArray(result)){
            //说明不是数组
            throw new Error("要导出的result数据必须是一个数组,数组里面为对象")
        }
        if(!excelPath){
            throw new Error("保存Excel的路径地址不能为空");
        }
        let excelData=[];
        excelData.push(Object.keys(result[0]));  //构建表头的数组
        //构建Excel所需的数据
        result.forEach(item=>{
            let values = Object.values(item);
            excelData.push(values);
        });

        let excelBuffer=xlsx.build([
            {
                name:"Sheet1",
                data:excelData
            }
        ]);
        fs.writeFileSync(excelPath,excelBuffer);
    }
 }
 module.exports=ExcelUtil;
  • throw new Error() 向外边抛一个错误 ,外边可以通过try...catch去捕捉到这个错误
  • try...catch可以捕捉到错误 ,也可以捕捉到reject

path模块

path模块是NodeJS里面内置模块,主要用于处理路径相关的问题,其核心常用方法列举3个

  1. join()拼接路径
  2. isAbsolute()判断路径是否是绝对路径
  3. resolve()。相对路径拼接以后然后再转换成绝对路径
/**
 * 主要是对path模块进行学习
 */
const path=require("path");
//path模块主要用于处理nodejs里面的路径 ,它常用的方法主要有三个
//NodeJS里面,与路径相关的两个内置变量
//console.log(__dirname);   //当前文件夹目录的路径  
//console.log(__filename);  //当前文件的路径 

//path.join()接拼路径,它可以将多个路径拼在一起
console.log(path.join(__dirname,"../"));
console.log(path.join(__dirname,"./views","index.html"));
//------------------------------------
console.log(path.isAbsolute("D:\\H1904\\1005\\code\\100502\\views"));        //  直接在当前电脑的C盘下面去找
console.log(path.isAbsolute("./views"));   //   ./views 的当前文件夹下面找views文件夹    相对路径 

// resolve干了两件事情 1.拼接路径,2.转换成绝对路径
console.log(path.resolve("./views","index.html"));

输出结果

d:\H1904\1005\code\
d:\H1904\1005\code\100502\views\index.html
true
false
d:\H1904\1005\code\100502\views\index.html

fs模块

fs模块是NodeJS用于处理文件系统与文件流的模块,可以理解为File SystemFile Stream

  1. 读取文件readFile()readFileSync()

    这两个方法,一个是异步 ,一个是同步的

    readFile异步操作

    /**
     * fs模块  重要,非常重要,真的非常重要
     * 计要用于操作计算机系统里面的文件,文件夹等
     * 增,删,改,遍历
     */
    const fs = require("fs");   //FileSystem    FileStream
    const path=require("path");
    //fs读取文件  现在读取的是文本文件,后期我会在项目里面让大家读视频,音频,图片
    fs.readFile(path.join(__dirname,"./abc.txt"),{encoding:"utf-8"},(err,data)=>{
        if(err){
            //读取失败在err里
            console.log(err);
        }
        else{
            //读取成功在data里
            console.log(data);
        }
    });
    //读非文本文件的时候,就不要设置编码了
    fs.readFile(path.join(__dirname,"./item1.jpg"),(err,data)=>{
        if(err){
            console.log(err);
        }
        else{
            //非文本文件读出来得到的是一个Buffer缓冲区,(也就是一个二进制数据)
            console.log(data);
        }
    });
    //这一种方式 是异步读取文件 它需要通过回调处理,同时 fs模块还提供同步的操作方法
    

    readFileSync同步操作

    /**
     * fs模块,同步读取文件
     */
    
     const fs=require("fs");
     const path=require("path");
    
     //它是一个同步的方法,不需要使用回调  data就是读取的结果,但是要注意,同步的方法没有err,所以要用try...catch
     try {
        let data = fs.readFileSync(path.join(__dirname,"./abc.txt"),{encoding:"utf-8"});
        console.log(data); 
     } catch (error) {
         console.log(error); 
     }
    
  2. writeFile/writeFileSync直接写文件以及appendFilesync追加文件

    /**
     * fs  写文件
     */
    const fs=require("fs");
    const path=require("path");
    //---------在此处,我们只讲同步,异步的方式请参考读取文件的异步方法-------------
    
    
    let str="年轻的时候,连生活当中的一些多愁善感都要渲染得惊天动地\r";
    //把上面这句话写到当前文件夹下面的biaogege.txt里面
    
    //在写的过程当中,如果发现没有这个文件,它会自己创建
    fs.writeFileSync(path.join(__dirname,"./biaogege.txt"),str,{encoding:"utf-8"});
    
    let str1="长大以得才发现,在工作与生活中,越痛,越不动声色,越苦,越保持沉默\r";
    fs.appendFileSync(path.join(__dirname,"./biaogege.txt"),str1,{encoding:"utf-8"});
    
  3. existsSync()判断文件是否存在,mkdirSync()创建文件夹

    /**
     * fs模块应用一,复制文件
     */
    
    //item1.jpg复制10份,放到imgs文件夹下面,名称为a1.jpg.....a10.jpg
    const path = require("path");
    const fs = require("fs");
    
    //第一步:先读
    let data = fs.readFileSync(path.join(__dirname, "./item1.jpg"));
    //第二步:判断有没有imgs文件夹,如果有,直接写,如果没有创建一个文件夹
    let imgPath = path.join(__dirname, "./imgs"); //现在要判断imgPath这个文件夹路径是否存在
    
    let flag = fs.existsSync(imgPath); //判断是否存在,如果true则代表存在,如果false则代表不存在
    if (!flag) {
        //说明这个路径不存在,我要创建一个
        fs.mkdirSync(imgPath);
    }
    
    for (let i = 1; i <= 10; i++) {
        fs.writeFileSync(path.join(imgPath, `a${i}.jpg`), data);
    }
    
  4. renameSync()重命名

    fs模块没有提供剪切的功能,我们可以通过这个方法实现剪切的功能

    /**
     * 文件重命名
     */
    //将当前文件夹下面的def.txt重命名为 hello.txt
    
    const fs=require("fs");
    const path=require("path");
    
    //fs没有提供剪切的功能 ,rename可以当成剪切
    fs.renameSync(path.join(__dirname,"./def.txt"),path.join(__dirname,"./txt","hello.txt"));
    

    如果路径不相同,则是剪切的效果

  5. 获取文件状态fs.stat()

    /**
     * 获取文件或文件夹状态
     */
    const fs = require("fs");
    const path = require("path");
    
    let path1 = path.join(__dirname, "./txt"); // txt文件夹路径 
    
    let path2 = path.join(__dirname, "./abc.txt"); //abc.txt文件的路径 
    
    //得到状态1
    let stat1 = fs.statSync(path1);
    //得到状态2
    let stat2 = fs.statSync(path2);
    
    console.log(stat1.isDirectory());   //判断是否是一个文件夹
    
    console.log(stat2.isFile());    //判断是否是一个文件
    
  6. 删除文件unlinkSync()

    /**
     * fs 删除文件或文件夹
     */
    const fs = require("fs");
    const path = require("path");
    
    //第一步:请删除当前目录下面的biaogege.txt这个文件
    let filePath = path.join(__dirname, "./biaogege.txt");
    
    //删除之前要判断是否存在
    if(fs.existsSync(filePath)){
        //存在我就删
        fs.unlinkSync(filePath);
    }
    
  7. readdirSync()读取某一个文件夹,返回当前文件夹下面的子文件夹与文件

  8. rmdirSync()删除文件夹

    在删除这个文件夹之前,必须先保证这个文件夹是空的,如果不是空的,要先删除这个文件

    /**
     *  fs 递归删除文件与文件夹
     */
    const fs=require("fs");
    const path=require("path");
    
    let filePath=path.join(__dirname,"./imgs");
    
    /**
     * @name deletePath  删除一个路径
     * @param {string} oldPath 要删除的路径 
     */
    function deletePath(oldPath){
        let stat = fs.statSync(oldPath);
        if(stat.isDirectory()){
            //说明是文件夹
            let paths = fs.readdirSync(oldPath);   //读取当前文件夹,返回当前文件夹下面的所有子文件夹以及文件名
            paths.forEach(item=>{
                let newPath = path.join(oldPath,item);
                deletePath(newPath);
            });
            //经过上面的遍历,所胡的文件都删完了,现在就可以删文件夹了
            fs.rmdirSync(oldPath);
        }
        else if(stat.isFile()){
            //说明是文件,直接删除
            fs.unlinkSync(oldPath);
        }
    }
    deletePath(filePath);
    

axios与cheerio模块

在NodeJS里面,我们经常会使用axios进行模拟的http请求,模拟http请求有三个常用的模块

  • axios
  • flyio
  • superagnet

现在我们使用axios+cheerio进行一次数据爬取操作

/**
 * axios模拟HTTP请求,去抓取数据
 */

const axios = require("axios");
const cheerio = require("cheerio");
const path=require("path");
const fs=require("fs");


async function getMovie() {
    let url = "https://www.iqiyi.com/dianying/?vfrm=pcw_home&vfrmblk=C&vfrmrst=712211_channel_dianying";
    let resp = await axios.default.get(url);
    //请求回来的结果在resp.data里面,现在使用cheerio来解析
    let $ = cheerio.load(resp.data);
    //接下来就要分析HTML的格式,来获取需要的数据
    let arr = []; //保存需要的数据
    $(".qy-mod-li").each((index, ele) => {
        let nm = $(ele).find(".link-txt").text().trim();                //标题
        let showInfo = $(ele).find(".sub").text().trim();               //上映信息
        let sc = $(ele).find("text-score").text().trim();               //评分
        let imgSrc = $(ele).find(".qy-mod-cover").attr("data-src");     //图片地址
        //将上面的信息组成一个对象以后放到数组里面去
        arr.push({
            nm,
            showInfo,
            sc,
            imgSrc
        });
    });
    //现在我们已经将所有的数据都放到数组里面去了
    //现在我们将数组转换成了JSON字符串,然后写入到文件里面去
    fs.writeFileSync(path.join(__dirname,"movie.txt"),JSON.stringify(arr),{encoding:"utf-8"});

    //要开始抓图片了,要把每一个图片地址都请求一次
    let imgPath=path.join(__dirname,"./downloadImgs");  //保存图片的文件夹路径 
    arr.forEach(async item=>{
        if(item.imgSrc){
            let resp = await axios.default.get("https:"+item.imgSrc,{responseType:"stream"});
            //把所有的图片都保存在downloadImgs人文件夹下面,首先要判断是否有这个文件夹,如果没有就创建 
            if(!fs.existsSync(imgPath)){
                fs.mkdirSync(imgPath);
            }
            //防止文件名相同,我们使用当前的时间毫秒数做为文件名
            let imgStream=fs.createWriteStream(path.join(imgPath,`${Date.now()}.png`));
            //流管道对接
            resp.data.pipe(imgStream);
        }
    });
}

getMovie();

本案例以爱奇异为案例,抓取爱奇异电脑信息以及图片。其中cheerio模块是NodeJS解析HTML字符串的模块

nodemailer模块

/**
 * 163发送邮件
 */

const nodemailer = require("nodemailer");
let transport = nodemailer.createTransport({
    // nodemailer不自带163配置,需要我们自己配置
    host:"smtp.163.com",
    port:465,
    secure:true,   //是否启用信息加密
    auth:{
        user:"mh475201314@163.com",
        pass:"lovesnxxxxxxx314"    //这个地方填授权码
    }
});

//发送邮件
transport.sendMail({
    //from从谁的邮箱发
    from:"mh475201314@163.com",   
    //to是发送到哪些邮箱
    to:"365055754@qq.com,997432124@qq.com,624889455@qq.com,2698524785@qq.com,1498159866@qq.com,462171275@qq.com,649769923@qq.com,1584419346@qq.com,www.wuxi123@qq.com,hyong2927@163.com",
    // 邮件标题
    subject:"这是标哥的一封测试邮件",
    text:`
        尊敬的用户:
        您好!
        你本次注意的邮件验证码为:${parseInt(Math.random()*4)},如非本人操作,请忽略!
                                        H1904项目中心
                                        ${new Date().toLocaleString()}
    `,
    //邮件附件
    attachments:[
        {
            filename:"我的相片",
            path:"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1072114723,434819413&fm=26&gp=0.jpg",
            cid:"01"
        }
    ]
},(err,info)=>{
    if(err){
        //邮箱发送失败的回调
        console.log(err);
    }
    else{
        //邮件发送成功的回调
        console.log(info);
    }
});

0

评论区