【学习前端第五十课】使用第三方模块去发送邮件

使用第三方模块去发送邮件

在使用node开发项目时候会涉及用户的注册,在这个环节里面,用户需要填写自己的邮箱,为了验证邮箱的真实性,我们一般会向邮箱内发送一个验证码或者是一个验证链接,让用户自己打开邮箱去接收

这个时候我们就需要用代码来发邮件

在node平台上面要实现这个功能依赖第三方模块实现,这个模块叫做 nodemailer

第一步:安装所需要的包

node install nodemailer --save

第二步:准备发送邮件的邮箱账号,我们这里以网易邮箱为例

邮箱中需要在设置中开启

开启之后,会多出一个授权设备

开启pop3和smtp之后,会出现一个授权密码与授权状态

协议类型协议功能服务器地址非SSL端口SSL端口号
STMP发送邮件smtp.163.com25465
POP接收邮件pop.163.com110995
IMAP接收邮件imap.163.com143993

nodejs对Excel文件的操作

首先先下载第三方包,node-xlsx

npm install node-xlsx --save

准备以恶搞Excel文件

读取Excel文件
const xlsx = require("node-xlsx");
const path = require("path");
const fs = require("fs");

//parse方法是一个专门用来接收数据类型为string或ArrayBuffer
//fs.readFileSync 返回的是一个buffer类型
let result = xlsx.parse(fs.readFileSync(path.join(__dirname,"/demo.xlsx")));
console.log(result);

读取的结果:

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

它的结果是一个数组集合,在这里集合里面有三个对象,这三个对象我们可以认为就是对应的excel表格当中的工作表,里面的name属性就是单独一个工作表标题,data里面就是当前工作表内的数据,然后每一个工作表形成一个对象,让后多个工作表对象组成一个excel数组,我们就认为这个excel数组其实就整个excel文件

然后现在我们开始往工作表里面填写一些内容然后获取出来看下data当中的结构

[
  [ '姓名', '性别', '年龄', '班级', '专业' ],
  [ '张三', '男', 20, '1班', '前端' ],
  [ '张三', '男', 20, '1班', '前端' ],
  [ '张三', '男', 20, '1班', '前端' ],
  [ '张三', '男', 20, '1班', '前端' ]
]

以上是获取到的data的数据结构,我们可以发现,data组成了一个二维数组,其中二维的部分每一个数组就相当于是一行的数据

将上面的数据转换成json格式

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

//parse方法是一个专门用来接收数据类型为string或ArrayBuffer
//fs.readFileSync 返回的是一个buffer类型
let result = xlsx.parse(fs.readFileSync(path.join(__dirname,"/demo.xlsx")));
let firstExcelTable = result[0];
//现在我们需要将上面的数据转换成JSON数据
let resultArr = [];
for(let i = 0; i < firstExcelTable.data.length; i++){
    //每循环一次,代表一行数据
    let obj = {};
    for(let j = 0; j < firstExcelTable.data[i].length; j++){
        let propertyName = firstExcelTable.data[0][j];  //取obj的属性名
        obj[propertyName] = firstExcelTable.data[i][j];  //对属性赋值
    }
    resultArr.push(obj);
}
fs.writeFileSync(path.join(__dirname,"/excel.json"),JSON.stringify(resultArr),{encoding:"utf8"});
console.log("写入成功")

生成excel表格

首先需要准备一个json数据

第一步:读取json文件
let result1 = fs.readFileSync(path.join(__dirname,"/excel.json"));  
//因为读取之后返回的是buffer类型,所以还需要进行toString的处理
let jsonStr = result1.toString();
let jsonObj = JSON.parse(jsonStr);  //将json字符串转换成对象

第二步:构造所需要的Excel数据结构

根据我们上面获取Excel表格的数据结构,还原一套一样的数据结构出来用于接收jsonObj里面的数据

let execlObj = {
    name:"sheet1",
    data:[]
}
第三步:转换数据
//构造第一行数据,也就是excel的表头,它就是我们对象的属性名
let excelFirstLine = Object.keys(jsonObj[0]);
//将第一行数据添加到data中
execlObj.data.push(excelFirstLine);
//接下来添加excel当中真正的数据,也就是每个对象属性值,Object.values()
jsonObj.forEach( item => {
    execlObj.data.push(Object.values(item));
});
第四步:根据数据生成excel文件
//Buffer可以理解成放在里面的一块数据
let excelBuffer = xlsx.build([execlObj]);
//把数据写入到硬盘中
fs.writeFileSync(path.join(__dirname,"/xin.xlsx"),excelBuffer,{encoding:"utf8"});
console.log("excel写入成功");

nodejs链接mysql数据库

安装第三方模块mysql

npm install mysql --save

创建数据库链接

const mysql = require("mysql");

const conn = mysql.createConnection({
    host:"127.0.0.1",
    port:3306,
    user:"root",
    password:"root",
    database:"h2003"
});

conn.connect(error => {
    if(error){
        console.log("链接数据库失败");
        console.log(error);
    }else{
        console.log("数据库链接成功");
    }
})

新增操作

let insertSql = `insert into test (name,age) value ("哈哈","18")`;
conn.query(insertSql,(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();  //断开当前链接
})

分析返回结果

OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0
}

上面的结果是数据库新增成功之后的结果,我们来分析下

insertId 当前数据表里面的id是自动增长,就会返回这个自动增长的id

changedRows 更改的行数

带参的新增

在执行sql语句的时候,如果sql语句当中有些东西还要替换怎么办?这个时候我们使用sql参数

let insertSql = `insert into test (name,age) value (?,?)`;
conn.query(insertSql,["李四",30],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})
修改操作
let updateSql = `update test set name = ? where age = ?`;
conn.query(updateSql,["王五",30],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})

分析修改结果

OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 34,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1
}

affectedRows说明当前几条数据受影响

changedRows 说明修改了几条数据

message 在服务被修改的时候返回的相关系统提示:Rows matched 带where匹配了几条数据,Changed代表修改了几条,Warnings 代表系统警告

删除操作
let deleteSql = `delete from test where age = ?`;
conn.query(deleteSql,[30],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})
查询操作

数据库的操作操作于之前的增,删,改都不属于同一类型的操作,它可以把查询后的结果返回跟用户

普通查询
let strSql = `select * from test`;
conn.query(strSql,[30],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})

查询结果

[
  RowDataPacket { name: '哈哈', age: 18 },
  RowDataPacket { name: '张三', age: 20 }
]

查询的时候返回的是一个数组,这个数里面的每一个对象就是一行数据,用列名做属性名,当前列的值作为属性值

带参查询
let strSql = `select * from test where age = ?`;
conn.query(strSql,[20],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})

注意:如果有了参数,直接在sql语句里面是 ?替代

模糊查询
let strSql = `select * from test where age like ?`;
conn.query(strSql,[18],(error,result) => {
    if(error){
        console.log("执行失败");
    }else{
        console.log(result);
    }
    conn.end();
})
SQL语句的动态拼接

注意:这个是重点

我们先来看下面两句

select * from h2003 where 1

select * from h2003

这两条sql语句执行效果是一样的,但是有区别

第一条sql语句的后面我们添加了一个where,这样后期即使再有条件,我们也只需要直接链接一个and,如果说第二条就很麻烦了

//先定义三个变量,模拟用户再页面输入的三个值
let sname = "";
let ssex = "男";
let snation = "回族";

//准备要执行的sql语句
let strSql = `select * from stuinfo where 1`;
let arr = [];

//开始动态拼接
if(sname){
    strSql = strSql + ` and sname like ?`
    arr.push(sname);
}
if(ssex){
    strSql = strSql + ` and ssex = ?`
    arr.push(ssex);
}
if(snation){
    strSql = strSql + ` and snation like ?`
    arr.push(snation);
}


//执行拼接好的sql语句
conn.query(strSql,arr,(error,result) => {
    if(error){
        console.log("sql语句执行失败");
        console.log(error);
    }else{
        console.log("sql语句执行成功");
        console.log(result);
    }
    conn.end();
})
分页查询
select 列 from 表 where 条件 limit offset,Count

offset代表跳过多少条

Count代表取多少条数据

如果设一个变量pageIndex代表页码,每页显示5条数据,那么h2003数据表中的分页查询怎么写?

slect * from h2003 limit (pageIndex - 1) * 5,5
//分页查询
let sname = "";
let ssex = "男";
let snation = "";
let pageIndex = 1;

let strSql = `select * from stuinfo where 1`;
let arr = [];

//开始动态拼接
if(sname){
    strSql = strSql + ` and sname like ?`
    arr.push(sname);
}
if(ssex){
    strSql = strSql + ` and ssex = ?`
    arr.push(ssex);
}
if(snation){
    strSql = strSql + ` and snation like ?`
    arr.push(snation);
}

//拼接分页条件
strSql += `limit ${(pageIndex - 1) * 5},5`

conn.query(strSql,arr,(error,result) => {
    if(error){
        console.log("sql语句执行失败");
        console.log(error);
    }else{
        console.log("sql语句执行成功");
        console.log(result);
    }
    conn.end();
})
/** * ckUI * author:h_yang * version:1.8.1 * beforeVersion:1.7.7 * * API(属性级): * $.ckTrim(str),返回值为去掉前后空格 str: jquery对象||元素ID||字符串 * $.ckIsEmail(str, ifAlert),返回是否为正确邮箱格式 str: jquery对象||元素ID||字符串 ifAlert: 是否弹出错误信息 * $.ckIsUrl(str, ifAlert), 返回是否是正确的URL格式地址 str: jquery对象||元素ID||字符串 ifAlert: 是否弹出错误信息 * $.ckIsMobile(str, ifAlert), 返回是否是正确格式电话号 str: jquery对象||元素ID||字符串 ifAlert: 是否弹出错误信息 * $.ckSetCookie(name, value, path, time),设置cookie name: key value: 值 path: 域 time: 存活时间(s) * $.ckGetCookie(name), 获取cookie, name: key值 * $.ckDelCookie(name), 删除cookie, name: key值 * $.ckObjToJsonStr(obj), obj对象转json字符串,如果出现异常,则返回"" * $.ckObjToJson(obj), obj对象转json对象, 如果出现异常则返回new Object() * $.ckIsEmpty(str, ifAlert), 返回是否为空值, str: jquery对象||元素ID||字符串 ifAlert: 是否弹出错误信息 * $.ckMul(arg1, arg2), 乘法 * $.ckAdd(arg1, arg2), 加法 * $.ckSub(arg1, arg2), 减法 * $.ckDiv(arg1, arg2), 除法 * $.ckMustNumber(e, obj), 只能输入数字, 属性级函数 * $.ckFmtMoney(s, n), s: 金额, n: 保留的小数位数 * $.ckRbkMoney(s), s: 格式化之后的金额 * $.ckGoto(url), 跳转url地址 * $.ckShade(flag, time), 遮罩, flag: boolean类型,true为开启,false关闭,在开启时,重复点击则中断线程, time为持续时间,默认为4秒 * $.ckGetContext(), 返回应用程序上下文全路径 * $.ckGotoView(uri), 跳转带上下文的地址,uri: 请求地址,如果uri第一位不是/ 则自动加/ * $.ckCheckCard(str, ifAlert), 返回是否是正确身份证号, str: jquery对象||元素ID||字符串 ifAlert: 是否弹出错误信息 * $.ckPostToNewView(url, args) post形式跳转页面,避免参数暴露在地址栏中 * * 更新日志: * 2017-01-10更新日志: $.ckShade(true) 遮罩功能,一次调起为开启,在遮罩参数为true的时候再次调起会终止线程, $.ckShade(false) 为关闭遮罩 * 2017-01-16更新日志: 遮罩加入显示图片 * 2017-01-18更新日志: $.ckGetContext() 返回为不带/的根项目路径 * 2017-01-20更新日志: $.ckShade(boolean, time), boolean 是否显示遮罩 time: 显示时间为毫秒, 遮罩默认显示5秒 * 2017-02-08更新日志: $.ckMaxLength(length) 加入最大输入长度限制函数 length: 最大长度数 * 2017-02-10更新日志: $.ckWhatFrameWork() 0: 安卓 1: 苹果 2: winphone 3 other * 2017-02-15更新日志: $.ckAlert(option) 弹出组件 * 2017-02-18更新日志: $.ckSetCookie(), 新增参数time 单位:秒 为cookie过期时间 * 2017-02-25更新日志: $.ckAnchor(), 页面锚点,返回上个页面自动定位到上次浏览的位置 * 2017-03-07更新日志: $.ckIsUrl(), 是否是URL地址 * 2017-03-09更新日志: $.ckGotoView(uri), 带项目根路径的跳转 * 2017-03-09更新日志: $.ckCheckCard(card, ifAlert), 检测身份证号 card: 身份证号||元素ID||jquery对象 ifAlert: 是否打印错误信息 * 2017-03-13更新日志: 修复$.ckIsEmpty对入参的校验规则 * 2017-04-05更新日志: 加入两种限制函数,$.ckMustEnAndNumber(适配 . -) & $.ckMustEnAndCN & $.ckMustEnAndNumberAndCn * 2017-04-07更新日志: 加入自定义过滤,$.ckRegular(expression) expression 为正则表达式 * 2017-04-07更新日志: 改进了must相关函数的触发条件,现在可以兼容移动端了 * */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值