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
实现了异步编程async
与await
与Promise
进行结合,异步转同步的代码,请参考上一节笔记
数据库数据导出为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个
- join()拼接路径
- isAbsolute()判断路径是否是绝对路径
- 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 System
或File Stream
-
读取文件
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); }
-
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"});
-
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); }
-
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"));
如果路径不相同,则是剪切的效果
-
获取文件状态
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()); //判断是否是一个文件
-
删除文件
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); }
-
readdirSync()
读取某一个文件夹,返回当前文件夹下面的子文件夹与文件 -
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);
}
});
评论区