parameter
参数校验工具
公共的
rule
:
required
:默认true
,是否必须type
:类型,不同的类型有对应的rule
convertType
:将输入参数转成特定的类型。支持int
、number
、string
和boolean
,也支持一个自定义转换方法的函数default
:默认值widelyUndefined
:覆盖全局的options.widelyUndefined
不同type
独有的rule
类型 | rule | convertType | 备注 |
---|---|---|---|
int |
max 、min |
int |
最大值和最小值;别名integer |
number |
max 、min |
number |
最大值和最小值 |
date |
string |
YYYY-MM-DD 格式的数据 |
|
dateTime |
string |
YYYY-MM-DD HH:mm:ss 格式的数据;别名datetime |
|
id |
string |
/^\d+$/ 格式的数据 |
|
boolean |
boolean |
布尔值;别名bool |
|
string |
allowEmpty 、format 、max 、min 、trim |
string |
字符串 |
email |
allowEmpty |
string |
邮箱,验证规则RFC 5322 |
password |
compare 、max 、min |
string |
min 最小长度默认6 |
url |
string |
验证规则web url | |
enum |
values |
值必须是values 中的一个 |
|
object |
rule |
对象 | |
array |
itemType 、rule 、max 、min |
数组 |
// rules examples
var rule = {
name: 'string',
age: {type: 'int', max: 200},
gender: ['male', 'female'],
working: 'boolean',
salary: {type: 'number', min: 0},
birthday: 'date',
now: 'dateTime',
id: 'id',
childrens: {
type: 'array',
itemType: 'object',
required: false,
rule: {
name: 'string',
age: 'int',
gender: ['male', 'female'],
birthday: {type: 'date', required: false}
}
},
mate: {
type: 'object',
required: false,
rule: {
name: 'string',
age: 'int',
gender: ['male', 'female'],
birthday: {type: 'date', required: false}
}
}
}
-
下载
parameter
:npm i parameter --save
-
在
middleware/
目录下添加parameter.js
文件
const Parameter = require('parameter');
function parameter(translate) {
return async (ctx, next) => {
let parameter;
if (typeof translate === 'function') {
parameter = new Parameter({
translate,
// convert: true
})
} else {
parameter = new Parameter()
}
ctx.verifyParams = function(rules, params) {
if (!rules) {
return;
}
if (!params) {
params = ['GET', 'HEAD'].includes(this.method.toUpperCase())
? this.request.query
: this.request.body;
// copy
params = Object.assign({}, params, this.params);
}
const errors = parameter.validate(rules, params);
if (!errors) {
return;
}
const arrError = errors.map(error => error.field + ' ' + error.message)
throw(new ctx.errs.ParameterException(arrError.join(';')))
}
await next()
}
}
module.exports = parameter
- 修改
app.js
文件,配置中间件
const parameter = require('./middleware/parameter')
app.use(parameter())
- 在代码中使用
router.get('/test/parameter', async ctx => {
const props = ctx.query
ctx.verifyParams({
name: 'string',
age: { type: 'int', convertType: 'int', max: 150, min: 0 }
}, props)
console.log(props)
ctx.body = 'ddd'
})
koa-json
koa
读取和修改json
-
下载
koa-json
:npm i koa-json --save
-
修改
app.js
,配置
const json = require('koa-json')
app.use(json())
koa-convert
对于比较老的使用Generate
函数的koa
中间件(< koa2
),官方提供了一个灵活的工具可以将他们转为基于Promise
的中间件供Koa2
使用,同样也可以将新的基于Promise
的中间件转为旧式的Generate
中间件。
-
下载
koa-convert
:npm i koa-convert --save
-
使用示例
const convert = require('koa-convert')
app.use(modernMiddleware)
// yield → async/await
app.use(convert(legacyMiddleware))
// compose
app.use(convert.compose(legacyMiddleware, modernMiddleware))
function * legacyMiddleware (next) {
// before
yield next
// after
}
function modernMiddleware (ctx, next) {
// before
return next().then(() => {
// after
})
}
koa-compress
当响应体比较大时,我们一般会启用类似Gzip
的压缩技术减少传输内容,koa-compress
提供了这样的功能,可根据需要进行灵活的配置。
-
下载
koa-compress
:npm i koa-compress --save
-
修改
app.js
,配置中间件
const compress = require('koa-compress')
// app.use(compress({
// threshold: 2048
// }))
app.use(compress({
// 只有在请求的content-type中有gzip类型,我们才会考虑压缩,因为zlib是压缩成gzip类型的
filter: function(content_type) {
return /text/i.test(content_type);
},
// 阀值,当数据超过1kb的时候,可以压缩
threshold: 1024,
// zlib是node的压缩模
flush: require('zlib').Z_SYNC_FLUSH
}))
koa-multer
koa-multer
是一个node.js
中间件,用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。它是写在 busboy
之上非常高效。
备注:Multer
不会处理任何非 multipart/form-data
类型的表单数据,意思就是我们要上传图片必须在form
表单上面加 multipart/form-data
-
下载
koa-multer
:npm i koa-multer --save
-
引入配置
koa-multer
模块
const multer = require('koa-multer')
// 配置
var storage = multer.diskStorage({
// 文件保存路径
destination: function (req, file, cb) {
// 注意路径必须存在
cb(null, 'public/uploads/')
},
//修改文件名称
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split(".")
cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1])
}
})
// 加载配置
var upload = multer({ storage: storage })
- 使用
koa-multer
router.post('/doAdd', upload.single('face'), async (ctx, next) => {
ctx.body = {
filename: ctx.req.file.filename,//返回文件名
body:ctx.req.body
}
});
- 不同图片上传到不同的地方
// router
const uploadController = require('../controller/upload');
const router = require('koa-router')();
// 文件上传
const multer = require('koa-multer');
const settingUpload = (str) => {
// 配置 -- 上传app logo
let storage = multer.diskStorage({
// 文件保存路径
destination: function (req, file, cb) {
cb(null, `static/uploads/${str}`)
},
// 修改文件名称
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split(".");
cb(null, Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
})
// 加载配置
return multer({ storage: storage });
}
// 路由
router.post('/avatar', settingUpload('avatar').single('file'), uploadController.avatarUpload)
.post('/package', settingUpload('package').single('file'), uploadController.packageUpload);
module.exports = router;
// controller
const multer = require('koa-multer');
// 计算文件大小,将字节转为 KB 或者 MB
const getSize = size => {
size = size / 1024;
if(size < 1024){
size = size.toFixed(2) + "KB"
}else{
size = size / 1024
size = size.toFixed(2) + "MB"
}
return size
}
// 应用的logo上传
const avatarUpload = async (ctx, next) => {
const host = ctx.request.origin;
const src = ctx.req.file.path.slice(6).replace(/\\/g, "/");
ctx.success({ logo: host + src })
}
// 安装包上传
const packageUpload = async (ctx, next) => {
const host = ctx.request.origin;
const src = ctx.req.file.path.slice(6).replace(/\\/g, "/");
ctx.success({
src: host + src,
size: getSize(ctx.req.file.size)
})
}
module.exports = {
avatarUpload,
packageUpload
}
- 使用
koa-multer
上传多个图片
router.post('/doAdd', upload.fields([{ name: 'pic', maxCount: 1 }, { name: 'aaa', maxCount: 1 }]), async (ctx, next) => {
console.log(ctx.req.files)
})
node-uuid
在项目开发中我们常需要给某些数据定义一个唯一标识符,便于寻找,关联。
-
下载
node-uuid
:npm i node-uuid --save
-
在代码中使用
const uuid = require('node-uuid')
// 基于时间戳生成
const id = uuid.v1()
// 随机生成,一般不用这种形式。这种形式还是有一定几率重复的
const id = uuid.v4()
nodemailer
node
中发送邮件
-
下载
nodemailer
:npm i nodemailer --save
-
修改
config/index.js
文件,添加配置
const config = Object.assign({}, envConfig, {
// ...
email: {
// 邮箱服务的主机,如smtp.qq.com
host: 'smtp.163.com',
port: 465,
// 开启安全连接
// secure: true,
// 用户信息
auth: {
user: 'xxxx', // 邮箱
pass: 'xxxx' // 授权码,不是密码
}
}
})
- 在
utils/
目录下添加email.js
文件
const nodemailer = require("nodemailer")
const emailConfig = require('../config').email
/**
* tolist 接收方的邮箱 //'li@latelee.org, latelee@163.com',//收件人邮箱,多个邮箱地址间用英文逗号隔开
* subject 邮件主题 标题
* cclist 抄送 //'li@latelee.org, latelee@163.com',//收件人邮箱,多个邮箱地址间用英文逗号隔开
* text 邮箱文本
* html 邮箱html格式的文本
* attachments 附件[{
* filename: 'img1.png', // 改成你的附件名
* path: 'public/images/img1.png', // 改成你的附件路径
* cid : '00000001' // cid可被邮件使用
* }]
*/
async function sendEmail(tolist, subject, cclist, text, html, attachments) {
// 对465为 true,对其他端口为 false
emailConfig.secure = (emailConfig.port == 465)
// 使用默认的SMTP传输创建可重用的传输器对象
const transporter = nodemailer.createTransport(emailConfig)
const mailOptions = {
from: emailConfig.auth.user, // 谁发的
to: tolist, // 发给谁
subject: subject, // 主题
// text: 'this is an example by nodemailer', // 文本内容
// html: '', // html模板
// attachments: [ // 附件信息
// {
// filename: '',
// path: ''
// }
// ]
}
cclist && (mailOptions['cc'] = cclist)
text && (mailOptions['text'] = text)
html && (mailOptions['html'] = html)
if(attachments && attachments!== isJSON(JSON.stringify(attachments))) {
mailOptions['attachments'] = attachments
}
// 发送邮件
const res = await transporter.sendMail(mailOptions)
return res
}
function isJSON(str) {
if (typeof str == 'string') {
try {
const obj = JSON.parse(str)
return (typeof obj == 'object' && obj )
} catch(e) {
return false
}
}
}
module.exports = {
sendEmail
}
- 在代码中使用
router.get('/test/email', async ctx => {
const res = await sendEmail(/* ... */)
ctx.success({
email: res
})
})
备注:
- 需要先设置邮箱,开启
POP3/SMTP
服务或者IMAP/SMTP服务
- 开启之后会有一个授权码。填写到
config/index.js
文件的邮箱配置中
qr-image
生成图片二维码插件
-
下载
qr-image
:npm i qr-image --save
-
代码中使用
const qr = require(qr-image)
router.get('/test/qr', async ctx => {
const url = 'http://www.wmm66.com/'
// 生成的是可读的流数据
const img = qr.image(url)
// 生成的是buffer,可以转成base64的字符串
// const img = qr.imageSync(url)
// const baseimg = Buffer(img).toString('base64')
ctx.type = 'image/png'
ctx.body = img
})
svg-captcha
图片验证码插件
-
下载
svg-captcha
:npm i svg-captcha --save
-
在代码中使用
const svgCaptcha = require('svg-captcha')
router.get('/test/captcha', async ctx => {
const cap = svgCaptcha.create({
size: 4, // 随机长度
inverse: false, // 翻转颜色
fontSize: 36, // 字体大小
noise: 3, // 噪声线条数
width: 80, // 宽度
height: 30, // 高度
})
console.log(cap.text.toLowerCase())
ctx.type = 'image/svg+xml'
ctx.body = cap.data
})
调用
create()
之后,会返回一个对象,结构如下:{data: '', text:'' }
data
:验证码svg
图片text
:验证码字符
create()
的参数如下
size: 4
:验证码长度ignoreChars: '0o1i'
:验证码字符中排除0o1i
noise: 1
:干扰线条的数量inverse: false
:翻转颜色fontSize: 36
:字体大小color: true
:验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有background: '#cc9966'
:验证码图片背景颜色width: 80
:宽度height: 30
:高度
createMathExpr(options)
创建算术式验证码
const svgCaptcha = require('svg-captcha')
router.get('/test/captcha', async ctx => {
const cap = svgCaptcha.createMathExpr({})
console.log(cap.text.toLowerCase())
ctx.type = 'image/svg+xml'
ctx.body = cap.data
})
captchapng
图片验证码插件
-
下载
captchapng
:npm i captchapng --save
-
在代码中使用
const captchapng = require('captchapng')
router.get('/test/captcha2', async ctx => {
const cap = parseInt(Math.random() * 9000 + 1000)
const p = new captchapng(80, 30, cap)
p.color(0, 0, 0, 0)
p.color(80, 80, 80, 255)
const base64 = p.getBase64()
ctx.success({
code: 'data:image/png;base64,' + base64,
})
// 直接返回图片
// 把base64码转成buffer对象
// const dataBuffer = new Buffer(base64, 'base64')
// ctx.type = 'image/png'
// ctx.body = dataBuffer
})
发表评论